用私有基函数覆盖 public 虚函数?

Override public virtual function with private base function?

让我们考虑具有以下接口的两个 classes AB

class A {
public:
    virtual void start() {} //default implementation does nothing
};

class B {
public:
    void start() {/*do some stuff*/}
};

然后是第三个 class,它继承自两者,A 是公开的,因为它实现了这个 "interface",B 是私有的,因为那是实现细节。

然而,在这个特定的实现中,start() 只需要包含对 B::start() 的调用。所以我想我可以使用快捷方式并执行以下操作:

class C: public A, private B {
public:
    using B::start;
};

并完成它,但显然它不起作用。所以我得到 using private base function doesn't work to override virtuals。由此,有两个问题:

编辑:一些精确度:

Is there any way to make this work as I supposed it may have worked?

您应该覆盖成员函数并显式调用 B::start():

class C: public A, private B {
public:
    void start() override { B::start(); }
};

Why would the compiler accept this code as valid? As I see it there are now two start() functions with the exact same signature in C and yet the compiler seems fine with it and only calls A::start().

你说得对,在 C 中有两个成员函数可以访问(A::start()B::start())。在 class C 中,如果不覆盖 start() 或通过执行 using ...::start() 使任何基础 类 的 start() 可见,您将在尝试时遇到歧义错误使用来自 C 的对象的非限定名称查找来调用成员函数。

class A {
public:
    virtual void start() { std::cout << "From A\n"; }
};

class B {
public:
    void start() { std::cout << "From B\n"; }
};

class C: public A, private B {
};

int main(){
    A* a = new C();
    a->start();       //Ok, calls A::start()

    C* c = new C();
    c->start();       //Error, ambiguous         
}

要解决这个问题,您必须使用限定名称,例如:

    C* c = new C();
    c->A::start();       //Ok, calls A::start()

现在,在 class C 中执行 using B::start() 只是声明 start() 引用 B::start() 每当从 C 的对象中使用此类名称时

class A {
public:
    virtual void start() { std::cout << "From A\n"; }
};

class B {
public:
    void start() { std::cout << "From B\n"; }
};

class C: public A, private B {
public:
     using B::start();
};

int main(){
    A* a = new C();
    a->start();       //Ok, calls A::start()

    C* c = new C();
    c->start();       //Ok, calls B::start()
}

using B::start 使函数 void B::start()C 中可见,但不会覆盖它。调用make上述所有不合格的成员函数调用,调用B::start(),应该覆盖C中的成员函数,使其调用B::start()

class A {
public:
    virtual void start() { std::cout << "From A\n"; }
};

class B {
public:
    void start() { std::cout << "From B\n"; }
};

class C: public A, private B {
public:
    void start() override { B::start(); }
};

int main(){
    A* a = new C();
    a->start();         //Ok, calls C::start() which in turn calls B::start()
                        //    ^^^^^^^^^^^^^^^^ - by virtual dispatch

    C* c = new C();
    c->start();         //Ok, calls C::start() which in turn calls B::start()

}