C++从具有相同虚拟函数名的多个基类继承
C++ inherit from multiple base classes with the same virtual function name
我试过这个代码:
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文件中。
谢谢~~
C
具有两个虚拟函数foo
,它们分别继承自A
和B
。但是函数void C::foo()
覆盖both:
[class.virtual]/2
如果在类
Base
和类Derived
中声明虚拟成员函数vf
,直接或间接从Base
派生,则声明具有与Base::vf
相同的名称、参数类型列表、cv限定符和ref限定符(或不存在相同的限定符)的成员函数vf
,则CCD_ 12也是虚拟的(无论是否如此声明)并且它覆盖CCD_。
正如我在评论中已经指出的,[dcl.含义]/1禁止在(成员)函数的声明中使用限定id:
当声明符id被限定时,声明应引用该限定符引用的类或命名空间的先前声明的成员[…]"
因此,任何virtual void X::foo();
作为C
内部的声明都是非法的。
代码
class C : public A, public B
{
virtual void foo();
};
是AFAIK覆盖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();
}
您只有一个虚拟函数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;
}
我遇到了同样的问题,意外地打开了第二个线程。抱歉。对我有效的一种方法是在没有多重继承的情况下解决它。
#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()rn");
}
};
class IB: public B
{
virtual void foo(void)
{
printf("IB::foo()rn");
}
};
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方法不再存在歧义。
您可以使用不同的函数参数来解决这种模糊性。
在现实世界的代码中,这样的虚拟函数会起作用,所以它们通常已经有了以下两种:
- A和B中的不同参数,或
- A和B中的不同返回值,可以将其转换为[out]参数,以解决此继承问题;否则
- 您需要添加一些标记参数,优化器会丢弃这些参数
(在我自己的代码中,我通常发现自己处于情况(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;
};
与adigostin的解决方案相比略有改进:
#include <iostream>
struct A {
virtual void foo() = 0;
};
struct B {
virtual void foo() = 0;
};
template <class T> struct Tagger : T {
struct tag {};
void foo() final { foo({}); }
virtual void foo(tag) = 0;
};
using A2 = Tagger<A>;
using B2 = Tagger<B>;
struct C : public A2, public B2 {
void foo(A2::tag) override { std::cout << "A" << std::endl; }
void foo(B2::tag) override { std::cout << "B" << std::endl; }
};
int main() {
C c;
A* pa = &c;
B* pb = &c;
pa->foo(); // A
pb->foo(); // B
return 0;
}
假设基类CCD_ 22和CCD_。
- C++ 继承:基类中重载 operator+ 的 2 次在派生类中无法正常工作
- 使用 "using" 关键字继承基类的复制和移动构造函数
- 获取继承基类类型的元组
- C++:继承基类方法
- 当我们想要私下继承基类时,为什么要进行名称公开
- 继承基类,定义基类的原型方法,但从第三个对象调用子类的方法
- C++继承基类使用派生类的成员
- C++-Do派生类继承基类的静态成员
- C++ OOP 体系结构:决定是从基类声明对象还是继承基类
- 继承基类时遇到问题
- 继承基类的一部分
- 我不希望派生类继承基类的构造函数
- 派生类继承基类赋值运算符
- C++继承基类析构函数
- 派生类是否继承基类使用的前向声明?
- 我继承基类以及多重继承的超类
- c++中的派生类构造函数可以继承基类构造函数吗?
- 继承的问题:派生类不继承基类
- 使子类继承基类的现有实例
- c++防止继承基类的特定公共成员