c – ‘使用’关键字从多个虚拟继承的函数中进行选择

我有一个类(‘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草案中没有发现任何决定性的解释.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...