C ++从具有相同虚函数名的多个基类继承

时间:2013-08-23 08:36:29

标签: c++ function class virtual multiple-inheritance

我试过这段代码:

class A
{
    virtual void foo() = 0;
};

class B
{
    virtual void foo() = 0;
};

class C : public A, public B
{
    //virtual void A::foo(){}
    //virtual void B::foo(){}

    virtual void A::foo();
    virtual void B::foo();
};

void C::A::foo(){}
void C::B::foo(){}

int main()
{
    C c;
    return 0;
}

使用注释部分时可以,但是当我尝试在类声明之外编写定义时,编译器会报告错误。 我正在使用MSVC11编译器,有谁知道怎么写这个? 我需要将代码移动到cpp文件中。

谢谢~~

4 个答案:

答案 0 :(得分:20)

函数根据名称和参数类型覆盖基类的虚函数(参见下文)。因此,您的班级C两个虚拟函数foo,其中一个来自每个AB。但是函数void C::foo()会覆盖两者

[class.virtual] / 2

  

如果在类vf和类Base中声明虚拟成员函数Derived,直接或间接地从Base派生,则成员函数{{1使用同名, parameter-type-list ,cv-qualification和ref-qualifier(或不存在相同)声明为vf,然后Base::vf为也是虚拟的(无论是否如此声明)并且覆盖 Derived::vf

正如我在评论中所说,[dcl.meaning] / 1禁止在(成员)函数的声明中使用 qualified-id

  

declarator-id 被限定时,声明应引用先前声明的限定符引用的类或命名空间的成员[...]“

因此,任何Base::vf作为virtual void X::foo();内的声明都是非法的。

代码

C

是AFAIK覆盖class C : public A, public B { virtual void foo(); }; 的唯一方式,它会覆盖fooA::fooB::fooA::foo除了引入另一层继承之外,没有办法对B::foo#include <iostream> struct A { virtual void foo() = 0; }; struct B { virtual void foo() = 0; }; struct CA : A { virtual void foo() { std::cout << "A" << std::endl; } }; struct CB : B { virtual void foo() { std::cout << "B" << std::endl; } }; struct C : CA, CB {}; int main() { C c; //c.foo(); // ambiguous A& a = c; a.foo(); B& b = c; b.foo(); } 采用不同的行为:

{{1}}

答案 1 :(得分:4)

您只有一个虚拟函数foo

class A {
    virtual void foo() = 0;
};

class B {
    virtual void foo() = 0;
};

class C : public A, public B {
    virtual void foo();

};

void C::foo(){}
void C::A::foo(){}
void C::B::foo(){};

int main() {
    C c;
    return 0;
}

答案 2 :(得分:1)

您可以使用不同的功能参数来解决这种歧义。

在现实世界的代码中,此类虚函数可以执行某些操作,因此它们通常已经具有以下任一功能:

  1. A和B中的不同参数,或
  2. A和B中的不同返回值,可以将它们转换为[out]参数,以解决此继承问题;否则
  3. 您需要添加一些标签参数,优化器会丢弃这些参数。

(在我自己的代码中,我通常会遇到情况(1),有时在情况(2)中,而在情况(3)中从未出现过。)

您的示例是情况(3),看起来像这样:

class A
{
public:
    struct tag_a { };
    virtual void foo(tag_a) = 0;
};

class B
{
public:
    struct tag_b { };
    virtual void foo(tag_b) = 0;
};

class C : public A, public B
{
    void foo(tag_a) override;
    void foo(tag_b) override;
};

答案 3 :(得分:0)

我遇到了同样的问题,并意外地开了第二个线程。对不起。对我有用的一种方法是在没有多重继承的情况下解决它。

#include <stdio.h>

class A
{
public:
    virtual void foo(void) = 0;
};

class B
{
public:
    virtual void foo(void) = 0;
};


class C
{
    class IA: public A
    {
        virtual void foo(void)
        {
            printf("IA::foo()\r\n");
        }
    };
    class IB: public B
    {
        virtual void foo(void)
        {
            printf("IB::foo()\r\n");
        }
    };

    IA m_A;
    IB m_B;
public:
    A* GetA(void)
    {
        return(&m_A);
    }

    B* GetB(void)
    {
        return(&m_B);
    }
};

诀窍是将从接口(A和B)派生的类定义为本地类(IA和IB),而不是使用多重继承。此外,如果需要,这种方法还可以打开每个接口的多个实现的选项,这是使用多重继承无法实现的。 本地类IA和IB可以很容易地访问C类,因此接口IA和IB的实现可以共享数据。

每个界面的访问可以按如下方式进行:

main()
{
    C test;
    test.GetA()->foo();
    test.GetB()->foo();
}

......不再有关于foo方法的歧义。