C++ 基类如何在运行时确定方法是否已被覆盖?

int*_*pid 5 c++ virtual-functions

下面的示例方法旨在检测它是否已在派生类中被覆盖。我从 MSVC 得到的错误意味着尝试获取指向“绑定”成员的函数指针是完全错误的,但我看不出这应该是一个问题的逻辑原因(毕竟,它将在this->vtable 中))。是否有任何非hacky方法来修复此代码?

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”;
    }
};
Run Code Online (Sandbox Code Playgroud)

小智 3

没有办法确定方法是否已被重写,除了纯虚方法之外:它们必须在派生类中被重写并且是非纯的。(否则您无法实例化对象,因为类型仍然是“抽象”的。)

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

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

void A::f() {}
Run Code Online (Sandbox Code Playgroud)

根据您的评论,“如果该方法没有被重写,则意味着可以安全地尝试将调用映射到其他方法。”

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();
  }
};
Run Code Online (Sandbox Code Playgroud)

现在,任何派生类都可以提供它们自己的行为,或者如果它们不这样做,则遗留的将被用作后备。do_method virtual 是私有的,因为派生类不能调用它。(NonLegacy 可以根据需要将其设置为受保护或公开,但默认与其基类具有相同的可访问性是一个好主意。)