C++ 基类是否可以具有作为派生类实例的成员?

C++ 基类是否可以具有作为派生类实例的成员?,c++,inheritance,c++11,C++,Inheritance,C++11,我可以有一个基类,其成员是派生类的实例吗?我应该如何向前声明或包含派生类定义?还是我应该用另一种方式来做这件事 // base.h class DerivedClass; // Is forward declaration sufficient? class Base { public: virtual ~Base(); virtual void DoStuff() = 0; void DoSomethingWithD() { d_.Foo(); } prote

我可以有一个基类,其成员是派生类的实例吗?我应该如何向前声明或包含派生类定义?还是我应该用另一种方式来做这件事

// base.h

class DerivedClass;  // Is forward declaration sufficient?

class Base {
 public:
  virtual ~Base();
  virtual void DoStuff() = 0;
  void DoSomethingWithD() {
    d_.Foo();
  }
 protected:
  DerivedClass d_;
};



这将适用于您,请参阅更改注释:

#include <memory>

class Derived;

class Base {
 public:
  virtual ~Base();
  virtual void DoStuff() = 0;
  void DoSomethingWithD();      // no longer defined in-line
 protected:
  std::unique_ptr<Derived> d_;  // storing as a pointer as Derived is still incomplete
};

class Derived : public Base {
 public:
  Derived();
  void DoStuff();
  void Foo();
 private:
  Derived(const Derived&);
  void operator=(const Derived&);
};

class OtherDerived : public Base {
 public:
  OtherDerived();
  void DoStuff();
 private:
  OtherDerived(const OtherDerived&);
  void operator=(const OtherDerived&);
};

// definition moved down here where Derived is a complete type
void Base::DoSomethingWithD() { 
  d_->Foo();
}
#包括
类派生;
阶级基础{
公众:
虚拟~Base();
虚空DoStuff()=0;
void DoSomethingWithD();//不再在线定义
受保护的:
std::unique_ptr d_;//作为派生的指针存储仍然不完整
};
派生类:公共基{
公众:
派生();
void DoStuff();
void Foo();
私人:
派生(常量派生&);
void运算符=(常量派生&);
};
类:公共基{
公众:
OtherDerived();
void DoStuff();
私人:
OtherDerived(const OtherDerived&);
void运算符=(const OtherDerived&);
};
//定义移到此处,其中派生的是完整类型
void Base::DoSomethingWithD(){
d_->Foo();
}

您可能可以使用CRTP并将派生类的实例作为基中的指针来实现这一点。不,您不能。即使使用CRTP。
Base
的大小取决于
派生的
的大小,派生的
的大小取决于
Base
的大小。但是,您可以存储指向派生类的指针或引用。@DyP-Ah。我不需要会员。我可以用指针来对付。那么,远期申报就足够了。谢谢。@Dyp你错过了我评论的后半部分。我提到的CRTP有点笨拙;)@特洛伊嗯。。。。哎呀!;)“将指针存储为类型仍然是不完整的”,严格地说,我认为这并不完全正确。[basic.types]/5“已声明但未定义的类,或大小未知或元素类型不完整的数组,是一个未完全定义的对象类型。未完全定义的对象类型和无效类型是不完整的类型。”虽然
派生的
不完整,但
唯一的\u ptr
是,因为您不能将其用作成员,否则:[class.mem]/9“非静态数据成员不应具有不完整的类型。”也就是说,您确实需要一个越位(ctor和)dtor。
unique\u ptr
允许保留指向不完整类型的指针。它只需要在调用
unique\u ptr
上的成员函数时完成(例如,其析构函数)。因为
Derived
的定义在
Base
的定义之后是可见的,所以这不是问题。
// other_derived.h

#include "base.h"

class OtherDerived : public Base {
 public:
  OtherDerived();
  void DoStuff();
 private:
  OtherDerived(const OtherDerived&);
  void operator=(const OtherDerived&);
};
#include <memory>

class Derived;

class Base {
 public:
  virtual ~Base();
  virtual void DoStuff() = 0;
  void DoSomethingWithD();      // no longer defined in-line
 protected:
  std::unique_ptr<Derived> d_;  // storing as a pointer as Derived is still incomplete
};

class Derived : public Base {
 public:
  Derived();
  void DoStuff();
  void Foo();
 private:
  Derived(const Derived&);
  void operator=(const Derived&);
};

class OtherDerived : public Base {
 public:
  OtherDerived();
  void DoStuff();
 private:
  OtherDerived(const OtherDerived&);
  void operator=(const OtherDerived&);
};

// definition moved down here where Derived is a complete type
void Base::DoSomethingWithD() { 
  d_->Foo();
}