所以我正在使用组合将一组对象组合在一起,所有对象都是从基类派生出来的,比如说Component。 E.g:
class Component {
public:
Component();
...
private:
int m_address;
...
};
class SpecializedComponent: public Component {
public:
SpecializedComponent()
... //and so on
};
class SpecializedComponent2: public Component {
public:
SpecialIzedComponent2()
... //and so on
};
class ComponentHolder{
SpecializedComponent* m_descriptiveName;
SpecializedComponent2* m_descriptiveName2;
// and so on... many different types of components
}
因此,每个SpecializedComponentX将通过网络与单个数据源进行通信,每个数据源都有自己唯一的地址。这些地址在参数文件中指定。目前,我正在解析参数文件,并在派生类构造函数中初始化m_address
- 这是因为每个m_address都是由我们正在初始化的对象类型指定的。
每个SpecializedComponentX都有一些我想在基类Component中执行的常用功能。所以,我启动了一个与基类Component相关的线程,对吧?当然 - 有道理。直到我意识到我还没有该组件的目标地址 - 因为该对象尚未完全构建。我想在ctor中启动基类线程,但我还不知道m_address
。
我能想到解决这个问题的唯一方法是提供一个(简单的)虚函数void start()
,一旦对象完全构造,派生类就可以调用它来旋转线程。这是有效的和适当的设计选择还是有一种我可以忽略的模式?谢谢。
答案 0 :(得分:0)
Component可以有一个构造函数,其中一个参数初始化m_address。
答案 1 :(得分:0)
如果这个常见功能以任何方式取决于SpecializedComponent,SpecializedComponent2的状态,或者这是一个SpecializedComponent或SpecializedComponent2,那么除非你传入参数,否则你不能在Component的构造函数中真正做到这一点。它。将类型标识符传递给Component构造函数来进行此类初始化有时是一种必要的恶魔。
但是,在这种情况下,您可以创建派生类可以调用的虚函数。但是,假设您将此虚函数调用放在SpecializedComponent构造函数中。如果你以后从这个(SuperSpecializedComponent)派生了另一个类并且对这个虚函数进行了ovrerride,你从SpecialzedComponent构造函数调用的调用甚至都不会。道德:不要从构造函数中调用虚函数。
我认为最干净的方法是采用两相结构。一个构造函数,用于对象的基本连接以及必须在使用之前调用的Init()方法。在完全构造所有对象之后,客户端代码(ComponentHolder?)可以调用此Init。
答案 2 :(得分:0)
为什么start()方法需要是虚拟的?
您可以将其设置为非虚拟并实现派生的构造函数 像这样:
SpecializedComponent::SpecializedComponent() {
m_address = getAddressFromParameterFile("SpecializedComponent");
start();
}
这比在对象完全后调用start()更好 因为两步构造容易出错。 (如果你这样做 需要两步施工,考虑工厂(或工厂方法) 确保只存在完全构造的对象。制作构造函数 私人和工厂(方法)的朋友。)
另一种方法是将地址的计算移出 对象构造。这将产生如下代码:
SpecializedComponent::SpecializedComponent(const std::string& address)
: Component(address)
{}
Component::Component(const std::string& address)
: m_address(address)
{
start();
}
这种方法提高了派生的可测试性 SpecializedComponents,因为它消除了对它的依赖 参数文件。
为方便起见,您可以为实例提供静态工厂方法 您的SpecializedComponents:
SpecializedComponent* SpecializedComponent::create() {
std::string address = getAddressFromParameterFile("SpecializedComponent");
return new SpecializedComponent(address);
}
BTW:考虑在ComponentHolder中保存shared_ptr,而不是原始指针。