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();
}