C ++基类包含一个派生类的实例(c++ base class contain instance o

2019-10-17 14:33发布

我想知道,如果有人可以给我解释一下我如何能够实现类似这样:

namespace advanced_cpp_oop
{
  class A
  {
    B b;
  };

  class B : public A
  {
  };
}

int main()
{
}

当一个基类的实例可以包含一个派生类的实例? 当上述代码被编译,生成以下错误:

g++ advanced_cpp_oop.cpp 
advanced_cpp_oop.cpp:8:5: error: ‘B’ does not name a type

的(几乎)等价的Java这确实编译的代码是:

public class AdvancedCppOop
{
  public static void main(String[] args)
  {
    A a;
  }
}

class A
{
  B b;
}

class B extends A
{
}

谢谢

Answer 1:

你需要一个指针和一个向前声明:

namespace advanced_cpp_oop
{
  class B;

  class A
  {
    B* b;
  };

  class B : public A
  {
  };
}

在你的C ++代码,你创建的实例class Bclass A ,因为编译器还不知道任何东西(特别是没有大小),这是不可能的class B

从我的答案代码,你需要动态分配的一个实例, class B ,并将其分配给b指针别的地方在你的代码。

在一个侧面说明,从设计的角度来看,这并没有什么意义,因为父类不应该依赖于一个子类。



Answer 2:

你有一些类型的指针,如的unique_ptr和向前声明做到这一点:

  class B;

  class A
  {
    std::unique_ptr<B> b;
  };

  class B : public A
  {
  };

这是愚蠢的,虽然你可能应该重新考虑你的设计。



Answer 3:

有C ++和Java之间的一个很重要的区别。 C ++是具有值语义的语言,而Java是参考语义的语言。 当在Java中创建的非基本型以外的任何一个变量,你是不是创建一个类型的对象,但这样的对象的引用。 与此相反,在C ++相同的构建体指的是实际的对象。

如果你记住这一点,这很容易理解,为什么下面不可能工作:

class Base {
   Derived d;
};
class Derived : Base {};

在C ++中的第一个定义意味着对象基地内部含有(未用参考)的派生类型的一个对象。 同时,导出通过继承的手段包含类型的碱的子对象。

这意味着,派生包含包含派生含碱...什么是基地或派生大小的基地?

在引用语义,或在C ++中,如果你使用指针语言,那是没有问题的。 基础对象包含衍生参照/指针 。 派生包含通过继承方式基类子对象。 基地的大小是公知的:所有其他字段加一参考/指针的大小。 源性的大小无论是基地的规模加上添加任何额外的成员。



Answer 4:

安德烈亚斯打我正确的答案,但我只想补充一点,Java代码的工作,只是因为Java对象是隐式指针举行(因此B b = new B(...);在整个Java代码洒语句),即使它看起来并不像它。 你原来的C ++代码不能正常工作(甚至B级的前向声明加入),因为编译器不知道B的对象有多大,因此不知道有多大的包含这将是一个对象。 在另一方面,所有的指针具有相同的尺寸(无论指向的类型),因此编译器没有这样的问题,当您的指针B的对象类A.替换B对象



文章来源: c++ base class contain instance of a derived class