C++ Understanding Functors Polymorphism

2019-06-21 16:29发布

问题:

I try to implement polymorphic functor objects (pure abstract base class and children) for understanding purposes only. My goal is to create many objects of the base class that use different implementations of the pure virtual functions.

When I create a pointer of the base class and set it equal to a new child class, I can not call the object as a function. The error is:

main.cpp:29:7: error: ‘a’ cannot be used as a function

Here is the code:

#include <iostream>

class foo{
public:
    virtual void operator()() = 0;
    virtual ~foo(){}
};

class bar: public foo{
public:
    void operator()(){ std::cout << "bar" << std::endl;}
};

class car: public foo{
public:
    void operator()(){ std::cout << "car" << std::endl;}
};


int main(int argc, char *argv[])
{

    foo *a = new bar;
    foo *b = new car;

    //prints out the address of the two object: 
    //hence I know that they are being created
    std::cout << a << std::endl;
    std::cout << b << std::endl;

    //does not call bar() instead returns the error mentioned above
    //I also tried some obscure variation of the theme:
    //*a(); *a()(); a()->(); a->(); a()();
    //just calling "a;" does not do anything except throwing a warning
    a();

    //the following code works fine: when called it print bar, car respectivly as expected
    // bar b;
    // car c;
    // b();
    // c();

    delete b;
    delete a;
    return 0;
}

My current understanding is that "foo *a" stores the address of of the function object "bar" in a (as shown by the cout statement). Hence dereferencing it "*a" should provide access to the function to which "a" is pointing to and "*a()" should call it.

But it does not. Can anyone tell me why?

回答1:

Since you have a pointer for a, you must dereference it to call the () operator:

(*a)(); // Best use parentheseis around the dereferenced instance


回答2:

When you dereference a you threw away the polymorphism, the foo::operator() should be called instead of bar::operator(), thus a pure virtual function call exception was thrown.