C++ 用函数指针覆盖纯虚函数

C++ Override Pure Virtual Function with Function Pointer

本文关键字:函数 覆盖 指针 C++      更新时间:2023-10-16

如果我有一个纯虚函数,可以用函数指针覆盖它吗?下面的场景(我知道它在语法上不是 100% 正确的):

#include<iostream>
using namespace std;
class A {
    public:
        virtual void foo() = 0;
};
class B : public A {
    public:
        B() { foo = &B::caseOne; }
        void caseOne() { cout << "Hello One" << endl; }
        void caseTwo() { cout << "Hello Two" << endl; }
        void (B::*foo)();
        void chooseOne() { foo = &B::caseOne; }
        void chooseTwo() { foo = &B::caseTwo; }
};
int main() {
    B b;
    b.(*foo)();
}

编辑:如果有人感兴趣,这是我完成我想做的事情的方式:

#include<iostream>
using namespace std;
class A {
    public:
        virtual void foo() = 0;
};
class B : public A {
    public:
        B() { f = &B::caseOne; }
        void caseOne() { cout << "Hello One" << endl; }
        void caseTwo() { cout << "Hello Two" << endl; }
        void (B::*f)();
        void chooseOne() { f = &B::caseOne; }
        void chooseTwo() { f = &B::caseTwo; }
        void foo() { (this->*f)(); }
};
int main() {
    B b;
    b.foo();
    b.chooseTwo();
    b.foo();
}

输出为:

Hello One
Hello Two

No.你用错了。在您的代码中,您正在尝试将成员函数指针分配给函数指针 - 它无法编译。

C++03 标准 10.3/2

如果在类 Base 和类中声明了虚拟成员函数 vf 派生、直接派生或间接来自 Base,与 Base::vf 具有相同名称和相同参数列表的成员函数 vf 是声明,则 派生::vf 也是虚拟的(无论它是否如此声明),它覆盖基数::vf.

正如@ForEveR所说,你的代码无法编译。但是,由于您实际需要的是能够在运行时切换B foo的实现,因此我们确实有解决方法:

#include <iostream>
using namespace std;
class A {
    public:
        virtual void foo() = 0;
};
class B : public A {
    private:
        void (B::*_f)();
    public:
        B() { chooseOne(); }
        void caseOne() {
            cout << "case one" << endl;
        }
        void caseTwo() {
            cout << "case two" << endl;
        }
        void chooseOne() { _f = &B::caseOne; }
        void chooseTwo() { _f = &B::caseTwo; }
        void foo() {
            (this->*_f)();
        }
};
int main(int argc, const char *argv[])
{
    A* b = new B();
    b->foo();
    ((B*)b)->chooseTwo();
    b->foo();
    return 0;
}

更新:

刚刚发现OP在问题中添加了他的答案,这和我的几乎一样。但我认为通过指针而不是实例对象调用foo更好,因为这可以表现出多态性的效果。此外,最好f隐藏为私有成员函数。

我认为在编译时,语法无法编译。您应该提供一个具有特定名称和相同参数列表的覆盖函数。