我试过这段代码:
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文件中。
谢谢~~
答案 0 :(得分:20)
函数根据名称和参数类型覆盖基类的虚函数(参见下文)。因此,您的班级C
有两个虚拟函数foo
,其中一个来自每个A
和B
。但是函数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();
};
的唯一方式,它会覆盖foo
和A::foo
。 B::foo
和A::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),有时在情况(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方法的歧义。