C++ 多重继承
上面的foo调用是一个编译时错误。 我想用obj的B部分调用foo,而不使用虚拟继承。我该怎么做呢 另外,在虚拟继承的情况下,为什么偏移量信息需要存储在vtable中。这可以在编译时确定。在上面的例子中,如果我们用D的对象传递foo,在编译时我们只能计算D的A部分的偏移量 使用施法-这里需要静态施法来施展继承权C++ 多重继承,c++,inheritance,multiple-inheritance,C++,Inheritance,Multiple Inheritance,上面的foo调用是一个编译时错误。 我想用obj的B部分调用foo,而不使用虚拟继承。我该怎么做呢 另外,在虚拟继承的情况下,为什么偏移量信息需要存储在vtable中。这可以在编译时确定。在上面的例子中,如果我们用D的对象传递foo,在编译时我们只能计算D的A部分的偏移量 使用施法-这里需要静态施法来施展继承权 #include<iostream> using namespace std; class A { int a; int b; public: v
#include<iostream>
using namespace std;
class A
{
int a;
int b;
public:
void eat()
{
cout<<"A::eat()"<<endl;
}
};
class B: public A
{
public:
void eat()
{
cout<<"B::eat()"<<endl;
}
};
class C: public A
{
public:
void eat()
{
cout<<"C::eat()"<<endl;
}
};
class D: public B, C
{
};
int foo(A *ptr)
{
ptr->eat();
}
main()
{
D obj;
foo(&(obj.B)); //error. How do i call with D's B part.
}
首先,obj没有名为B的成员。它从B继承,这意味着它将B的所有成员作为自己的成员继承
你可以致电:
使其工作。继承两次
使用双重继承会产生歧义——编译器无法知道要使用两个A基中的哪一个。如果您想有两个A基,有时您可能想这样做,您可以通过强制转换到B或C来在它们之间进行选择。这里最合适的默认强制转换是静态强制转换,因为它是最脆弱的可用类型,但是它不是真正需要的,它仍然比您的案例需要更强,因为您没有强制转换到派生类型。自定义安全强制转换模板应执行以下操作:
foo(static_cast<B*>(&obj));
有了这个,代码就可以编译了,但是有了这个解决方案,您无法在B::A或C::A之间进行选择,因为只有一个A,因此这可能不是您想要的
虚拟函数
此外,您的问题似乎混淆了两个不同的概念,虚拟继承意味着在两个中间基类之间共享一个基类,虚拟函数意味着允许通过基类指针调用派生类函数。如果希望使用指针调用B::eat,可以在不使用虚拟继承的情况下执行此操作。实际上,虚拟继承会阻止您使用虚拟函数执行此操作,如上所述:
class B: public virtual A ...
class C: public virtual A ...
如果您不能接受虚拟函数,那么编译时机制就是模板,如上所述。我认为静态转换不起作用 当您使用foo函数时,编译器只知道您有一个指向的指针,不管您作为参数传递的类型是什么
如果不使用虚拟继承,那么我认为没有办法从指向a的指针调用B函数。我怎么做。在编辑模式下,它正确显示。选择代码,然后用1和0按下按钮。如果foo不是虚拟的,则用obj的B、C或A部分调用foo将得到相同的结果。答:eat在任何情况下都会打印出来。吕克,你说得对;我忘了加那个。D类:公共B,C。你真的想保持B类的可见性模式为私有吗?不提及任何内容都会导致它在私有可见性模式下被继承。Suma,虚拟函数的vtable和虚拟继承相同吗?如果没有,虚拟继承表包含什么。使用虚拟继承时,虚拟表布局和调用虚拟函数的机制稍微复杂一些。看-但要做好准备,这是一个高级主题,理解它需要努力和耐心。
/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}
main()
{
D obj;
foo(safe_cast<B *>(&obj)); //error. How do i call with D's B part.
}
template <class TypeDerivedFromA>
int foo(TypeDerivedFromA *ptr)
{
ptr->eat();
}
class B: public virtual A ...
class C: public virtual A ...
class A
{
int a;
int b;
public:
virtual void eat()
{
cout<<"A::eat()"<<endl;
}
};