使用私有基本功能覆盖公共虚拟功能?

JBL*_*JBL 4 c++ overriding virtual-functions using-declaration private-inheritance

让我们考虑两个类,AB使用以下接口:

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

class B {
public:
    void start() {/*do some stuff*/}
};
Run Code Online (Sandbox Code Playgroud)

然后是A公开的第三个类,它是公开的,因为它实现了这个"接口",B私下因为它的实现细节.

但是,在此特定实现中,start()只需要包含一个调用B::start().所以我想我可以使用快捷方式并执行以下操作:

class C: public A, private B {
public:
    using B::start;
};
Run Code Online (Sandbox Code Playgroud)

并完成它,但显然它不起作用.所以我得using私有基本功能不起作用,以覆盖虚拟.由此,有两个问题:

  • 是否有任何方法可以使这项工作,因为我认为它可能有效?
  • 为什么编译器会接受此代码有效?正如我所看到的,现在有两个start()函数具有完全相同的签名C,但编译器看起来很好,只有调用A::start().

编辑:一些准确性:

  • 目标是C通过A指针操纵对象.
  • 我目前正在使用一个只调用的简单函数B::start(),我特别想知道一个using声明是否确实可以"覆盖"一个虚拟,如果没有,这是如何允许这两个函数共存的.
  • virtual为简单起见,我可能省略了一些像继承这样的东西.

Whi*_*TiM 5

是否有任何方法可以使这项工作,因为我认为它可能有效?

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

class C: public A, private B {
public:
    void start() override { B::start(); }
};
Run Code Online (Sandbox Code Playgroud)

为什么编译器会接受此代码有效?正如我所看到的,现在有两个start()函数在C中具有完全相同的签名,但编译器看起来很好并且只能调用A::start().

你是对的,有两个成员函数可以在C(A::start()B::start())中访问.并且,在class C没有通过执行a 覆盖start()或使start()任何基类可见的情况下using ...::start(),当尝试使用来自对象的未经验证的namelookup调用成员函数时,将会出现歧义错误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         
}
Run Code Online (Sandbox Code Playgroud)

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

    C* c = new C();
    c->A::start();       //Ok, calls A::start()
Run Code Online (Sandbox Code Playgroud)

现在,做一个using B::start()class C简单的声明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()
}
Run Code Online (Sandbox Code Playgroud)

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()

}
Run Code Online (Sandbox Code Playgroud)