5

让我们考虑两个类AB具有以下接口:

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

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

然后是从两者继承的第三个类,A公开是因为它实现了这个“接口”,而B私下是因为那是实现细节。

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

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

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

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

编辑:一些精度:

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

1 回答 1

6

有什么方法可以使这项工作像我认为的那样有效吗?

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

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

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

A::start()你是对的,在 C (和B::start())中有两个可访问的成员函数。并且在class C不覆盖start()start()通过执行 a 使任何基类可见的情况下using ...::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()

现在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()
}

using B::start使函数void B::start()在 中可见C,它不会覆盖它。调用使上述所有不合格的成员函数调用,调用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()

}
于 2017-01-23T14:41:40.903 回答