'using'关键字可从多个虚拟继承函数中进行选择

Sil*_*lan 10 c++ overriding virtual-functions using-declaration c++11

我有一个类('TestC'),它派生自另外两个类('TestA'和'TestB'),两个类都有一个具有相同签名的虚函数.

要通过'TestC'访问该功能,我必须告诉它使用哪个版本.如果我明确覆盖'TestC'中的函数并调用我想要的版本,这是有效的:

#include <iostream>

class TestA
{
public:
    virtual void test() {std::cout<<"a";}
};

class TestB
{
public:
    virtual void test() {std::cout<<"b";}
};

class TestC
    : public TestA,public TestB
{
public:
    void test() {TestB::test();}
};

int main(int argc,char *argv[])
{
    TestC c;
    TestA *a = static_cast<TestA*>(&c);
    a->test();
    c.test();
    for(;;);
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

输出:"bb"

这是预期的结果.但是,我注意到如果我使用'using'关键字,而不是显式覆盖函数,我会得到一些意想不到的行为:

class TestC
    : public TestA,public TestB
{
public:
    using TestB::test;
};
Run Code Online (Sandbox Code Playgroud)

(其他一切都是一样的)

输出:"ab"

谁可以给我解释一下这个?看起来'测试'突然变得不再虚拟了?有没有办法做到这一点,没有明确覆盖功能?(像"使用覆盖"之类的东西)

Jar*_*d42 10

using,你没有定义TestC::test(),但告诉它TestB::test()是可见的(所以隐藏TestA::test(),这是c.test()不明确的).


小智 4

using 声明永远不会覆盖虚函数。但是,它可以消除多重继承的歧义。在示例中a->test()调用:

\n\n
    \n
  1. TestC 的覆盖(调用 TestB::f)
  2. \n
  3. TestB 的覆盖(TestC 没有覆盖)
  4. \n
\n\n

以下(菱形)虚拟继承中的 using 声明不提供所需的最终重写:

\n\n
struct Base {\n    virtual void f();\n};\nstruct A : virtual Base {\n    virtual void f() override {}\n};\nstruct B : virtual Base {\n    virtual void f() override {}\n};\n\nstruct Derived : A, B {\n    // error: no unique final overrider for \xe2\x80\x98virtual void Base::f()\xe2\x80\x99 in \xe2\x80\x98Derived\xe2\x80\x99\n    using A::f;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

更多示例:

\n\n
#include <iostream>\n\n// Single Inheritance\n// ==================\n\nnamespace Single {\n\nstruct A {\n    virtual void f() { std::cout<<"A\\n"; }\n};\nstruct AA : A {\n    virtual void f() override { std::cout<<"AA\\n"; }\n};\n\nstruct Derived : AA {\n    // Has no impact if not called explicitly\n    using A::f;\n};\n\n} // namspace\n\n\n// Multiple Inheritance\n// ====================\n\nnamespace Multiple {\n\nstruct A {\n    virtual void f() { std::cout<<"A\\n"; }\n};\nstruct AA : A {\n    virtual void f() override { std::cout<<"AA\\n"; }\n};\nstruct B {\n    virtual void f() { std::cout<<"B\\n"; }\n};\nstruct BB : B {\n    virtual void f() override { std::cout<<"BB\\n"; }\n};\nstruct Derived : AA, BB {\n    // Disambiguate A::f (AA::f) and B::f (BB::f)\n    using A::f;\n};\n\n} // namspace\n\n\n// Test\n// ====\n\nint main() {\n    std::cout << "Single\\n";\n    {\n        Single::Derived d;\n        d.f();          // calls AA::f\n        d.Derived::f(); // calls A::f because of the using-declaration\n    }\n\n    std::cout << "Multiple\\n";\n    {\n        Multiple::Derived d;\n        d.f();          // calls AA::f\n        d.Derived::f(); // calls A::f because of the using-declaration\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

注:我在标准草案N4296中没有找到任何结论性的解释。

\n