我有一个类(‘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; }
输出:“bb”
这是预期的结果.但是,我注意到,如果我使用’using’关键字,而不是明确地覆盖该功能,我会收到一些意想不到的行为:
class TestC : public TestA,public TestB { public: using TestB::test; };
(其他一切都一样)
输出:“ab”
谁可以给我解释一下这个?看起来“测试”突然不再虚拟了吗?有没有办法做到这一点,没有明确的覆盖功能? (类似“使用覆盖”)
解决方法
使用声明永远不会覆盖虚拟函数.但是,它可以消除多重继承的歧义.在示例a-> test()中调用:
> TestC(调用TestB :: f)的覆盖
> TestB的覆盖(TestC没有覆盖)
以下(菱形)虚拟继承中的使用声明不提供必需的最终覆盖:
struct Base { virtual void f(); }; struct A : virtual Base { virtual void f() override {} }; struct B : virtual Base { virtual void f() override {} }; struct Derived : A,B { // error: no unique final overrider for ‘virtual void Base::f()’ in ‘Derived’ using A::f; };
更多例子
#include <iostream> // Single Inheritance // ================== namespace Single { struct A { virtual void f() { std::cout<<"A\n"; } }; struct AA : A { virtual void f() override { std::cout<<"AA\n"; } }; struct Derived : AA { // Has no impact if not called explicitly using A::f; }; } // namspace // Multiple Inheritance // ==================== namespace Multiple { struct A { virtual void f() { std::cout<<"A\n"; } }; struct AA : A { virtual void f() override { std::cout<<"AA\n"; } }; struct B { virtual void f() { std::cout<<"B\n"; } }; struct BB : B { virtual void f() override { std::cout<<"BB\n"; } }; struct Derived : AA,BB { // Disambiguate A::f (AA::f) and B::f (BB::f) using A::f; }; } // namspace // Test // ==== int main() { std::cout << "Single\n"; { Single::Derived d; d.f(); // calls AA::f d.Derived::f(); // calls A::f because of the using-declaration } std::cout << "Multiple\n"; { Multiple::Derived d; d.f(); // calls AA::f d.Derived::f(); // calls A::f because of the using-declaration } }
注意:我在标准N4296草案中没有发现任何决定性的解释.