其他分享
首页 > 其他分享> > c-多重继承

c-多重继承

作者:互联网

#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.

}

上面的foo调用是编译时错误.
我想用obj的B部分调用foo而不使用虚拟继承.我怎么做.

同样,在虚拟继承的情况下,为什么需要将偏移量信息存储在vtable中.这可以在编译时自行确定.在上述情况下,如果我们将foo与D的对象一起传递,则仅在编译时才能计算D的A部分的偏移量.

解决方法:

继承两次

对于双重继承,您会产生歧义-编译器无法知道您要使用两个A基.如果要有两个A底(有时可能需要这样做),则可以通过强制转换为B或C在它们之间进行选择.这里默认转换中最合适的是static_cast(作为最弱的可用),但是它是因为您没有转换为派生类型,所以不需要(它确实比案例需要更强大).定制的safe_cast模板应该可以完成以下工作:

/// 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.

}

编译时间类型-使用模板

Also, in case of virtual inheritance,
why the offset information need to be
stored in the vtable. This can be
determined at the compile time itself.
In the above case, if we pass foo with
D’s object, at compile time only we
can calculate the offset of D’s A
part.

这是一个误解.现在编写的foo函数除了是A *之外,没有关于ptr类型的编译类型信息,即使您传递B *或C *也是如此.如果希望foo能够根据传递的编译时间进行操作,则需要使用模板:

template <class TypeDerivedFromA>
int foo(TypeDerivedFromA *ptr)
{
  ptr->eat();
}

虚拟继承

您的问题提到虚拟继承.如果要使用虚拟继承,则需要指定:

class B: public virtual A ...

class C: public virtual A ...

使用此代码可以编译,但是使用此解决方案,您将无法在B :: A或C :: A(只有一个A)之间进行选择,因此这可能与您无关.

虚拟功能

此外,您的问题似乎混淆了两个不同的概念:虚拟继承(这意味着在两个中间基类之间共享一个基类)和虚函数(这意味着允许通过基类指针调用派生类函数).如果希望使用A指针调用B :: eat,则可以使用虚拟函数来执行此操作,而无需进行虚拟继承(实际上,虚拟继承会阻止您这样做,如上所述).

class A
{
   int a;
   int b;

   public:
   virtual void eat()
   {
      cout<<"A::eat()"<<endl;
   }
};

如果您不接受虚拟函数,则如上所述,其编译时机制是模板.

标签:c,inheritance,multiple-inheritance
来源: https://codeday.me/bug/20191010/1884096.html