Search code examples
c++function-pointersvirtualimplicit-conversionproxy-pattern

Error expected unqualified-id before '=' token when assigning a function pointer to the address of another function


I have the following program that I attempt to use function pointer to "save memory",by saving an address of a function to a member variable, which is the function pointer.

The function pointer is provideService_proxy which is defined by typedef void (* provideService_proxy )(std::string product).

I attempt to instantiate RealShop realShop_ and then call RealShop::provideService(string product). Furthermore, I want to save the address of provideService.

However, I encounter an error. Could you please help?

#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;
}

The error is:

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

Solution

  • There are several errors in my program:

    First, I got confused and forgot to declare a member function pointer:

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

    Instead, I had only the data type of function pointer by this line:

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

    Secondly, in order to assign the address of RealShop::provideService(string) to the function pointer, I need a more straighforward and explicitly defined the function pointer as:

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

    To save the address of RealShop::provideService(string), I have to do the following:

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

    In order to call RealShop::provideService(string) via function pointer, I have to do:

    (realShop_->*provideService_proxy)(product);
    

    This is my final program:

    #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;
    }
    

    Thanks @Vlad From Moscow for the help!