如果一个方法被重载,C ++基类如何在运行时确定? [英] How can a C++ base class determine at runtime if a method has been overridden?

查看:109
本文介绍了如果一个方法被重载,C ++基类如何在运行时确定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的示例方法旨在检测它是否已在派生类中重写。我从MSVC得到的错误意味着尝试获取一个绑定成员的函数指针是错误的,但我没有看到这是一个问题的逻辑原因(毕竟,它将在这个 - > vtable )是否有任何非黑客方法修复此代码?

  class MyClass 
{
public:
typedef void(MyClass :: * MethodPtr)();

virtual void方法()
{
MethodPtr a =& MyClass :: Method; // legal
MethodPtr b =& Method; //<<<错误C2276:'&':对绑定成员函数表达式的非法操作

if(a == b)//此方法未被覆盖?
throw不重写;
}
};


解决方案

无法确定方法覆盖,除了纯虚方法:它们必须在派生类中被重写和非纯。 (否则你不能实例化一个对象,因为类型仍然是抽象。)

  struct A {
virtual〜A(){} //抽象基础应该有一个虚拟dtor
virtual void f()= 0; //必须重写
}

您仍然可以提供纯虚拟方法的定义,如果派生类可能或必须调用它:

  void A :: f(){} 






根据您的评论,

  struct Base {
void method(){
do_method();
}

private:
virtual void do_method(){
call_legacy_method_instead();
}
};

struct Legacy:Base {
};

struct NonLegacy:Base {
private:
virtual void do_method(){
my_own_thing();
}
};

现在,任何派生类都可以提供自己的行为,他们没有。 do_method虚拟是私有的,因为派生类不能调用它。 (NonLegacy可能会适当地保护或公开,但默认与其基类相同的辅助功能是一个好主意。)


The sample method below is intended to detect whether or not it has been overridden in a derived class. The error I get from MSVC implies that it is simply wrong to try to get the function pointer to a "bound" member, but I see no logical reason why this should be a problem (after all, it will be in this->vtable). Is there any non-hacky way of fixing this code?

class MyClass
{
public:
    typedef void (MyClass::*MethodPtr)();  

    virtual void Method()
    {
        MethodPtr a = &MyClass::Method; // legal
        MethodPtr b = &Method;  // <<< error C2276: ‘&’ : illegal operation on bound member function expression

        if (a == b)     // this method has not been overridden?
            throw "Not overridden";
    }
};

解决方案

There is no way to determine if a method has been overridden, except for pure virtual methods: they must be overridden and non-pure in a derived class. (Otherwise you can't instantiate an object, as the type is still "abstract".)

struct A {
  virtual ~A() {} // abstract bases should have a virtual dtor
  virtual void f() = 0; // must be overridden
}

You can still provide a definition of the pure virtual method, if derived classes may or must call it:

void A::f() {}


Per your comment, "If the method had not been overridden it would mean it is safe to try mapping the call to the other method instead."

struct Base {
  void method() {
    do_method();
  }

private:
  virtual void do_method() {
    call_legacy_method_instead();
  }
};

struct Legacy : Base {
};

struct NonLegacy : Base {
private:
  virtual void do_method() {
    my_own_thing();
  }
};

Now, any derived class may provide their own behavior, or the legacy will be used as a fallback if they don't. The do_method virtual is private because derived classes must not call it. (NonLegacy may make it protected or public as appropriate, but defaulting to the same accessibility as its base class is a good idea.)

这篇关于如果一个方法被重载,C ++基类如何在运行时确定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆