1

Why is virtual behavior being prevented?

class  MyClass
    {
       //........
       virtual double GetX();
       virtual double GetSomethingElse();
       virtual double GetT();
       virtual double GetRR();
       //........

    };

    class Processor
    {
     private:
          typedef double (MyClass::*MemFuncGetter)();
          static map<std::string, MemFuncGetter> descrToFuncMap;

     public:
            static void Initialize();
            void Process(Myclass m, string);

    };

    void Processor::Initialize()
    {

         descrToFuncMap["X"]=&MyClass::GetX;
         descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
         descrToFuncMap["RR"]=&MyClass::GetRR;
         descrToFuncMap["T"]=&MyClass::GetT;
    };

    void Processor::Process(MyClass *ms, const std::string& key)
    {
         map<std::string, Getter>::iterator found=descrToFuncMap.find(key);
         if(found!=descrToFuncMap.end())
         {
            MemFuncGetter memFunc=found->second;
            double dResult=(ms).*memFunc();
            std::cout<<"Command="<<key<<", and result="<<result<<std::end;
          }
     } 
  • beef up your example with what you are seeing and what you expect to see. – Andrew Stein Mar 13 '09 at 15:46
  • please describe expected by you behavior and what you have. – bayda Mar 13 '09 at 15:47
  • @bb what don't u get? say Derived class inherits MyClass, so when I pass it to Processor::Process, I expect overriden method in Derived class called –  Mar 13 '09 at 16:17
  • And that's exactly what happens - other than a bunch of compile errors, and the slicing thing I pointed out (which is still in the Process class definition) it works just fine. – Eclipse Mar 13 '09 at 16:31

3 Answers3

7

This line here:

void Processor::Process(MyClass ms, const std::string& key)

Try replacing it with

void Processor::Process(MyClass &ms, const std::string& key)

What is happening is called slicing, even though you may have passed in a sub-class of MyClass, when you call Process, a new MyClass object is made on the stack using MyCLass's copy-constructor. This new object is a MyClass in everyway, including having MyClass's virtual table.

When you pass by reference, or with a pointer, no copy is made, and the reference to MyClass can be refering to an object that is really of a type SubClassOfMyClass.

Edit:

Well, the issue is with one of the many compile errors, if you get this all to compile it works just fine:

class  MyClass
{
public:
   //........
   virtual double GetX() { return 0.0; }
};

class  MyClass2 : public MyClass
{
public:
   //........
   virtual double GetX()  { return 1.0; }
};

class Processor
{
public:
   typedef double (MyClass::*MemFuncGetter)();
   static void Initialize();
   void Process(MyClass *m, const string &);
private:
   static map<std::string, MemFuncGetter> descrToFuncMap;
};

void Processor::Initialize()
{
     descrToFuncMap["X"]=&MyClass::GetX;
}

void Processor::Process(MyClass *ms, const std::string& key)
{
     map<std::string, MemFuncGetter>::iterator found=descrToFuncMap.find(key);
     if(found!=descrToFuncMap.end())
     {
        MemFuncGetter memFunc=found->second;
        double dResult=(ms->*memFunc)();
        std::cout<<"Command="<<key<<", and result="<<dResult<<std::endl;
      }
 }

map<std::string, Processor::MemFuncGetter> Processor::descrToFuncMap;

int main()
{
    Processor::Initialize();
    Processor p;

    MyClass2 mc2;
    p.Process(&mc2, "X");
}

Which outputs:

Command=X, and result=1

Community
  • 1
  • 1
Eclipse
  • 44,851
  • 20
  • 112
  • 171
1

Wow I have never seen a sample piece of code have so many other syntax errors before you get to the real problem.

When posting code it should be compilable by the people you want to help.
With the exception of the ONE bug you want others to help you with.

I am not sure what you are trying to achieve but it is not virtual functions. SO you should porobably re-name your question.

I presume your main problem is with this line:

MemFuncGetter memFunc=found->second;
double dResult=(ms).*memFunc();

Depending if you accepted Josh's advice the syntax should look like this.

 MemFuncGetter memFunc=found->second;
 double dResult=(ms.*memFunc)();    // MyClass& ms

 -- or

 double dResult=(ms->*memFunc)();   // MyClass* ms
Martin York
  • 257,169
  • 86
  • 333
  • 562
1

Have you considered using boost::bind and boost::function? It allows you to bind pointers to free/member functions and allows you to bind specific parameters as well for deferred calling.

Here's a tutorial/example: http://www.codeproject.com/KB/library/BoostBindFunction.aspx

wchung
  • 1,074
  • 9
  • 7