Ошибка ожидаемого неквалифицированного идентификатора перед токеном '=' при назначении указателя функции на адрес другой функции

У меня есть следующая программа, в которой я пытаюсь использовать указатель функции для «сохранения памяти», сохраняя адрес функции в переменной-члене, которая является указателем функции.

Указатель функции — это provideService_proxy, который определяется typedef void (* provideService_proxy )(std::string product).

Я пытаюсь создать экземпляр RealShop realShop_, а затем вызываю RealShop::provideService(string product). Кроме того, я хочу сохранить адрес provideService.

Однако я сталкиваюсь с ошибкой. Не могли бы вы помочь?

#include "iostream"
#include "string"
using namespace std;

// needed preprocessor to prevend loop include
#ifndef ISHOP
#define ISHOP
#include "string"

class IShop{
    public:
    IShop(){};
    virtual void provideService(std::string product) = 0;
    virtual ~IShop(){};
};
#endif

class RealShop: public IShop {
    public:
    RealShop(){};
    virtual ~RealShop(){};
    virtual void provideService(std::string product) override{
       cout<<"    shop is building "<<product<<" in warehouse"<<endl;
        if (specialOrder_ == true){
            specialService("Minh");
        }
        collectMaterial(); 
    } ;
    private:
    static const bool specialOrder_ = true;
    void collectMaterial(){
        cout<<"    collect material to build product"<<endl;
    };
    void specialService(std::string customerName){
        std::cout<<"provide custom order to customer "<<customerName<<std::endl;
        customerName_ = customerName;
    };     // newly added
    std::string customerName_;
};

class ShopProxy : public IShop {
    public:
    ShopProxy(){};
    virtual ~ShopProxy(){};
    virtual void provideService(std::string product) override {
        if ( realShop_ == nullptr  ) {                  
            std::cout<<"Proxy creates RealShop on request"<<std::endl;     
            // realShop_ = new RealShop();                               //create RealShop, call RealShop to do service
            // provideService_proxy = reinterpret_cast<provideService_proxy>(&RealShop::provideService);
            provideService_proxy = init_RealService (product);
        } 
        else{
            std::cout<<"Proxy can provide service"<<std::endl;
            // RealShop is available in Proxy's memory.
            // don't have to reload, just run logic
            // realShop_ ->provideService(product);         
            provideService_proxy (product);                     
        }
    };
    
    private:
    typedef void (* provideService_proxy )(std::string product);
    provideService_proxy  init_RealService ( std::string product ){
        realShop_ = new RealShop();
        return reinterpret_cast<provideService_proxy>(&RealShop::provideService);
    };

    RealShop * realShop_ = nullptr;    // safe initialization of pointer
};

int main()
{
    std::string requestProduct1 = "a doll";
    IShop * myShopProxy = new ShopProxy();
    // myShopProxy creates RealShop
    myShopProxy->provideService(requestProduct1);
    // myShopProxy already has RealShop, and can provide service.
    std::string requestProduct2 = "a toy";
    myShopProxy->provideService(requestProduct1);

    // delete myShopProxy will delete RealShop and data saved in memory
    delete myShopProxy;

    // create new proxy
    IShop * myShopProxy2 = new ShopProxy();
    // myShopProxy has to create new RealShop again and reload data.
    myShopProxy2->provideService(requestProduct1);

    delete myShopProxy2;
}

Ошибка:

error: expected unqualified-id before '=' token
   50 |             provideService_proxy = init_RealService (product);

Вы объявили provideService_proxy типом, а не элементом данных. Вы не можете назначать типы. Удалите typedef, если вы хотите, чтобы он был элементом данных.

user17732522 02.04.2023 16:32

«Я пытаюсь использовать указатель функции для «сохранения памяти», сохраняя адрес функции в переменной-члене»: не уверен, как это должно работать. Хранение указателя на функцию увеличивает использование памяти, поскольку значение указателя необходимо где-то хранить.

user17732522 02.04.2023 16:34

Кроме того, указатели функций и указатели функций-членов — это не одно и то же. Вы не можете хранить указатель на (нестатическую) функцию-член в указателе функции. reinterpret_cast не должно работать.

user17732522 02.04.2023 16:36

если я просто реализую realShop_->provideService(product), когда я вызываю вызов функции ShopProxy::provideService во второй раз, realShop->provideService(product) будет вызываться снова. Это требует добавления в стек вызовов дополнительной информации для вызова функции и потери памяти. Таким образом, я хочу сохранить адрес realShop_->provideService(product) в переменной-члене. Вы правы, указывая на мои ошибки. Но у меня все еще есть вопрос. Можно ли сохранить адрес функции в указатель члена?

Minh Pham 02.04.2023 17:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это объявление typedef

typedef void (* provideService_proxy )(std::string product);

объявляет имя provideService_proxy как псевдоним для типа void ( * )( std::string ). Он не объявляет никаких объектов типа указателя.

Таким образом, используя это имя typedef в качестве объекта в операторе выражения

provideService_proxy = init_RealService (product);

выдает ошибку.

Обратите внимание, что вам нужно объявить указатель на функцию-член, а не на отдельную функцию.

Я понимаю. Я запутался между типом данных provideService_proxy и переменной-членом, которая имеет тип данных как provideService_proxy.

Minh Pham 02.04.2023 16:57

после того, как я правильно определил тип данных и указатель на функцию-член. Я мог скомпилировать программу, но все еще имел ошибку seg fault. По сути, я удаляю typedef и использую void (* provideService_proxy )(std::string product) в качестве указателя на функцию. Я хотел бы реализовать функцию init_RealService, чтобы она сохраняла адрес realShop_->provideService(product) в указатель на функцию-член. Не могли бы вы предложить мне?

Minh Pham 02.04.2023 17:13

@MinhPham Это выражение realShop_->provideService(product) является вызовом функции. Вам нужно объявить указатель на функцию-член и присвоить ему имя функции.

Vlad from Moscow 02.04.2023 18:35

это указатель на функцию-член, которую вы имеете в виду? (realShop_->*provideService_proxy)(product)?

Minh Pham 02.04.2023 18:36

@MinhPham Чтобы объявить указатель на функцию-член, вам нужно написать, например, void ( RealShop::*pf )( std::string );

Vlad from Moscow 02.04.2023 19:09
Ответ принят как подходящий

В моей программе есть несколько ошибок:

Во-первых, я запутался и забыл объявить указатель на функцию-член:

void (* provideService_proxy )(std::string product) = nullptr;

Вместо этого у меня был только тип данных указателя функции по этой строке:

typedef void (* provideService_proxy )(std::string product)

Во-вторых, чтобы присвоить адрес RealShop::provideService(string) указателю на функцию, мне нужен более простой и явно определенный указатель на функцию как:

void (RealShop::* provideService_proxy )(std::string) = nullptr ;

Чтобы сохранить адрес RealShop::provideService(string), я должен сделать следующее:

realShop_ = new RealShop();
provideService_proxy = &RealShop::provideService;          
(realShop_->*provideService_proxy)(product);

Чтобы вызвать RealShop::provideService(string) через указатель функции, мне нужно сделать:

(realShop_->*provideService_proxy)(product);

Это моя последняя программа:

#include "iostream"
#include "string"
using namespace std;

// needed preprocessor to prevend loop include
#ifndef ISHOP
#define ISHOP
#include "string"

class IShop{
    public:
    IShop(){};
    virtual void provideService(std::string product) = 0;
    virtual ~IShop(){};
};
#endif

class RealShop: public IShop {
    public:
    RealShop(){
        cout<<"RealShop constructor"<<endl;
    };
    virtual ~RealShop(){
        cout<<"RealShop destructor"<<endl;
    };
    virtual void provideService(std::string product) override{
       cout<<"    shop is building "<<product<<endl;
    } ;
};

class ShopProxy : public IShop {
    public:
    ShopProxy(){
        cout<<"**ShopProxy constructor**"<<endl;

    };
    virtual ~ShopProxy(){ 
        cout<<"**ShopProxy destructor**"<<endl;
        delete realShop_;
    };
    virtual void provideService(std::string product) override {
        if ( realShop_ == nullptr  ) {                  
                
            //create RealShop, call RealShop to do service
            // provideService_proxy = (void (*)(std::string))init_RealService (product);            
            init_RealService (product);
        } 
        else{
            std::cout<<"Proxy can provide service"<<std::endl;
            // RealShop is available in Proxy's memory.
            // don't have to request another function call, and add to stack
            // save stack memory by using function pointer. 
            (realShop_->*provideService_proxy)(product);                 
        }
    };
    
    private:
    // typedef void (* functPtr )(std::string product);
    // void (* provideService_proxy )(std::string product) = nullptr;
    void (RealShop::* provideService_proxy )(std::string) = nullptr ;
    void init_RealService ( std::string product ){
        std::cout<<"Proxy creates RealShop on request"<<std::endl; 
        realShop_ = new RealShop();
        std::cout<<"init_RealService saves realShop_->provideService to function pointer"<<endl; 
        provideService_proxy = &RealShop::provideService;          
        (realShop_->*provideService_proxy)(product);
    };

    RealShop * realShop_ = nullptr;    // safe initialization of pointer
};

int main()
{
    std::string requestProduct1 = "REQUEST 1: a doll";
    IShop * myShopProxy = new ShopProxy();
    // myShopProxy creates RealShop
    myShopProxy->provideService(requestProduct1);
    // myShopProxy already has RealShop, and can provide service.
    std::string requestProduct2 = "REQUEST 2: a toy";
    myShopProxy->provideService(requestProduct2);

    // delete myShopProxy will delete RealShop and data saved in memory
    delete myShopProxy;

    // create new proxy
    std::string requestProduct3 = "REQUEST 3: a fan";
    IShop * myShopProxy2 = new ShopProxy();
    // myShopProxy has to create new RealShop again and reload data.
    myShopProxy2->provideService(requestProduct3);

    delete myShopProxy2;
}

Спасибо @Vlad From Moscow за помощь!

Другие вопросы по теме