考虑这个"设计" (遗漏了实施细节):
struct service {};
struct sub {
sub(service&) {}
service& s_;
};
struct sub_a: sub {
sub_a(service&) {}
};
struct sub_b: sub {
sub_b(service&) {}
};
struct top {
service svc_;
sub_ptr sub_;
};
基本上,我的top
对象包含sub_ptr
,但此指针所持有的实例需要访问svc_
才能实例化,这也在top
中。但是,我希望top
的用户能够选择sub
的类型(此处为sub_a
或sub_b
),而无法访问svc_
。
到目前为止,我的解决方案是让top
的构造函数像这样:
template <typename SubType>
top(std::unique_ptr<SubType>): sub_(new SubType(svc_)) {}
以下是用法:
auto t = top(std::unique_ptr<sub_b>());
但我不觉得这个解决方案很优雅。我可以编写函数(例如make_top_sub_b()
)来隐藏细节,但我想知道如何避免给出构造函数的虚拟指针?使top
模板化的类不是一种选择。
知道如何改善这个吗?谢谢,
答案 0 :(得分:1)
Liskov替换原则会听到sub_ptr
的用户不需要知道它持有的实现。
由于sub_ptr
包含在top
中,您可以说top
是用户。
sub
的构造需要通过它的工厂完成,它引用的service
的生命周期必须比保存引用的类的生命周期长。
在您的情况下,服务对象的生命周期似乎在top
,这意味着sub
的生命周期必须更短。
您可以拥有一个抽象的sub_factory
类,并从服务中创建一个。
e.g。
struct sub_factory
{
virtual sub* create( service_ & ) const = 0;
};
struct sub_a_factory : sub_factory
{
// detail, creates sub_a
};
struct sub_b_factory : sub_factory
{
// detail, creates sub_b
};
top::top( sub_factory const & fact ) :
sub_( fact.create( svc_ ) )
{
}
sub_factory_a afact;
sub_Factory_b bfact;
top ta( afact );
top tb( bfact );
请注意,您可以在此处使用初始化列表,因为svc_出现在您的类的sub_上方,因此首先进行初始化。