Ind*_*oad 6 c++ inheritance smart-pointers raii c++11
我经常遇到的一种情况是拥有一组类,Base并且Derived,Base类具有基类成员的所有权BaseMember,并且Derived该类具有指向同一对象的引用或指针,但是作为一个DerivedMember.
例如,一个UI面板类,它包含具有某些特殊控制功能的特定类型控件的特定实例,继承自包含常规控件并具有通用控件功能的通用类.
首先,说BaseMember是继承的DerivedMemeber.
不使用智能指针,我可能会这样做:
class Base
{
protected:
// receive ownership but only because we say so,
// someone else can still try to delete as it's "just a pointer"
Base(BaseMember* _bmember):
bmember(_bmember)
{}
public:
virtual ~Base()
{
// perform an owner's duty
delete bmember;
}
// functions that might be based on BaseMember + other base state
void SetMemberId(....)
{
bmember->SetId(baz);
}
private:
int baz;
BaseMember* bmember; //owned, but not smartly
}
class Derived: public Base
{
public:
Derived(DerivedMember* _dmember):
Base(_dmember),
dmember(_dmember)
{}
// functions that only make sense for Derived + Derived/Base state
void SetDerivedFrobulation()
{
// only a DerivedMember has frobulation, so only
// Derived allows users to access it
dmember->setFrobulation(foo);
}
private:
int foo; // some state
DerivedMember* dmember; // no ownership here
}
Run Code Online (Sandbox Code Playgroud)
使用智能指针(C++ 11及更高版本,特别是在这种情况下,我并不真正关心旧的C++),我很想做这样的事情,永远不要把Base/DerivedMember对象放到哑指针的地方,它可以如果在某处不方便的情况下发生异常泄漏.
class Base
{
protected:
// receive ownership
Base(std::unique_ptr<BaseMember> _member):
member(std::move(_member))
{}
virtual ~Base()
{}
public:
// public access functions here as before
private:
std::unique_ptr<BaseMember> member;
}
class Derived: public Base
{
public:
// pass the ownership down by unique_ptr
Derived(std::unique_ptr<DerivedMember> _dmember):
Base(std::move(_dmember)),
dmember(_dmember.get()) // _dmember is moved! SEGFAULT if access dmember later!
{}
// public access functions here as before
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
}
Run Code Online (Sandbox Code Playgroud)
正如我在那里所指出的那样,当你DerivedMember进入Derived构造函数时,你无法在类中"偷看" ,因为在查看之前它unique_ptr已经move消失Derived了.
我可以提供看的解决方案protected来访问BaseMember和static_cast荷兰国际集团回DerivedMember在Derived构造函数(后即Base构造完成),但这似乎丑陋的方式来获得访问回到我们放过虽然我们的手指变!
另一种方式可能是Base拥有指针的每个继承者,而base只是获得一个哑指针.在这种情况下,Base析构函数无法访问该成员,因为它已经消失了.它也会不必要地复制所有权逻辑.
我想要么:
Base/ Derived/ BaseMember/ DerivedMember系统的设计不是好的做法.这是一种重复使用的好模式,还是应该在其他地方寻找?
在一个核心库中,我有一个类DataInterpreter,它显示了数据的"某种解释" - 可以是一个字符串,一个图像等.然后由其他人TextInterpreter提交一个string.
然后,我有一个DataDisplayPanel类,它代表一个用于在抽象意义上显示的UI.确切地说,这个面板中的内容将取决于所使用的解释器:a TextInterpreter应该获得一个文本输入字段并说一个按钮来设置一些文本显示选项,并且处理中TextDisplayPanel,它具有解释器文本方面的"特殊"知识.
然后有一个DataAggregatePanel组合了许多DataDisplayPanels并提供一些影响所有显示(通过虚拟功能)的全局设置,并管理a中的面板std::vector<std::unique_ptr<DataDisplayPanel> >.这个聚合类根本不处理任何派生类,任何函数都是多态的并且在基类中定义.
在应用程序(依赖于核心库)中,这些类被扩展(通过继承或组合,无论哪个更有意义).例如,如果应用程序是WX GUI,我可能wxDataAggregatePanel包含wxTextDisplayPanel(和其他),所有这些都是wxPanels.在这种情况下,wxTextDisplayPanel可能拥有a wxTextEntry或者拥有或继承TextInterpreter并使用其TextInterpreter特定方法的知识来用文本框填充文本框.
您可以使用委托构造函数:
class Derived: public Base
{
public:
Derived(std::unique_ptr<DerivedMember> _dmember):
Derived(_dmember, _dmember.get())
{}
// public access functions here as before
private:
Derived(std::unique_ptr<DerivedMember>& _dmember, DerivedMember* ptr):
Base(std::move(_dmember)),
dmember(ptr)
{}
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
};
Run Code Online (Sandbox Code Playgroud)