通过存储指向成员函数的指针来实现虚拟行为

时间:2009-03-13 15:42:08

标签: c++

为什么要阻止虚拟行为?

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

3 个答案:

答案 0 :(得分:7)

这一行:

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

尝试用

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

正在发生的事情被称为slicing,即使你可能已经传入MyClass的子类,当你调用Process时,使用MyCLass的copy-constructor在堆栈上创建一个新的MyClass对象。这个新对象无论如何都是MyClass,包括拥有MyClass的虚拟表。

当您通过引用传递或使用指针传递时,不会进行任何复制,并且对MyClass的引用可以引用实际上属于SubClassOfMyClass类型的对象。

编辑:

嗯,问题在于许多编译错误之一,如果你把这一切都编译好就可以了。

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");
}

哪个输出:

  

Command = X,结果= 1

答案 1 :(得分:1)

哇,在你遇到真正的问题之前,我从来没有见过一段示例代码有太多其他语法错误。

发布代码时,应该由您想要帮助的人编译 除了ONE bug之外,您希望其他人帮助您。

我不确定你想要实现的目标,但它不是虚拟功能。因此,您应该可以重新命名您的问题。

我认为你的主要问题在于这一行:

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

根据您是否接受了Josh的建议,语法应如下所示。

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

 -- or

 double dResult=(ms->*memFunc)();   // MyClass* ms

答案 2 :(得分:1)

您是否考虑过使用boost :: bind和boost :: function?它允许您绑定指向free / member函数的指针,并允许您绑定特定参数以及延迟调用。

这是一个教程/示例: http://www.codeproject.com/KB/library/BoostBindFunction.aspx