我经常遇到的情况是拥有一组类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
}
使用智能指针(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
}
正如我在那里所指出的那样,你不能偷看&#34;偷看&#34;来自DerivedMember
构建器的Derived
类,因为在unique_ptr
查看之前move
为Derived
d。
我可以看到一个解决方案,在protected
构造函数中提供对BaseMember
和static_cast
DerivedMember
Derived
Base
的{{1}}访问权限。 Base
构造函数完成了),但这似乎是一种丑陋的方式来获取访问我们让我们的手指滑过的变量!
另一种方式可能是Base
的每个继承者拥有指针,而base只是获得一个哑指针。在这种情况下,Base
析构函数无法访问该成员,因为它已经消失了。它也会不必要地复制所有权逻辑。
我认为:
Derived
/ BaseMember
/ DerivedMember
/ DataInterpreter
系统的设计并不是一种好的做法。这是一个很好的重复使用模式,还是应该在其他地方寻找?
在核心库中,我有一个班级TextInterpreter
,它显示了一些解释&#34;数据 - 可以是字符串,图像等。然后由string
(其中包含DataDisplayPanel
继承。
然后我有一个TextInterpreter
类,它代表一个用于以抽象意义显示的UI。确切地说,此面板中的内容将取决于所使用的解释器:TextDisplayPanel
应该获得一个文本输入字段并说出一个按钮来设置一些文本显示选项,并在DataAggregatePanel
中处理,其中包含& #34;特别&#34;了解口译员的文本方面。
然后有DataDisplayPanels
组合了多个std::vector<std::unique_ptr<DataDisplayPanel> >
并提供了一些影响所有显示的全局设置(通过虚拟功能),并管理wxDataAggregatePanel
中的面板。这个聚合类根本不处理任何派生类,任何函数都是多态的,并在基类中定义。
在应用程序(依赖于核心库)中,这些类被扩展(通过继承或组合,无论哪个更有意义)。例如,如果应用程序是WX GUI,我可能wxTextDisplayPanel
包含wxPanels
(和其他),所有这些都是wxTextDisplayPanel
。在这种情况下,wxTextEntry
可能拥有TextInterpreter
并拥有或继承TextInterpreter
并使用其String s = "text string";
Random rand = new Random();
int randomIndex = rand.nextInt(s.length());//returns a random number between 0 and the index of the last character of the string
System.out.println(s.charAt(randomIndex));
特定方法的知识来填充文本框用一根绳子。
答案 0 :(得分:5)
您可以使用委托构造函数:
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
};