代码之家  ›  专栏  ›  技术社区  ›  jdt141

设计备选方案?组成和结构

  •  1
  • jdt141  · 技术社区  · 15 年前

    所以我使用组合将一组对象组合在一起,所有这些对象都是从一个基类派生的,比如组件。例如:

    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
    }
    

    因此,每个专用组件都将通过网络与单独的数据源通信,每个数据源都有自己的唯一地址。这些地址在参数文件中指定。目前,我正在分析参数文件和 m_address 是在派生类构造函数中初始化的-这是因为每个m_地址都是由我们正在初始化的对象类型指定的。

    每个专门的componentx都有一些我想在基类组件中执行的公共功能。所以,我启动了一个与基类组件关联的线程,对吗?当然-有道理。直到我意识到我还没有该组件的目标地址——因为对象还没有完全构造好。我想在ctor中旋转基类线程,但我不知道 兆地址 然而。

    我唯一能想到的解决这个问题的方法就是提供一个(简单的)虚拟函数, void start() ,派生类可以在对象完全构造后调用以使线程旋转。这是 有效的 适当的 设计选择还是有一个我可以忽略的模式?谢谢。

    3 回复  |  直到 15 年前
        1
  •  0
  •   Hans Passant    15 年前

    组件可以具有一个参数初始化m_地址的构造函数。

        2
  •  0
  •   Tarydon    15 年前

    如果这个通用功能以任何方式依赖于专用组件、专用组件2的状态,或者依赖于它是专用组件或专用组件2的事实,那么您不能在组件的构造函数中真正执行它,除非您向它传递参数。有时将类型标识符传递给组件构造函数以在那里进行此类初始化是必要的。

    但是,在这种情况下,可以创建派生类可以调用的虚拟函数。但是,假设您将此虚拟函数调用放在专用组件构造函数中。如果以后从这个(超专用组件)派生出一个更进一步的类,并且重写这个虚拟函数,那么从SpecialzedComponent构造函数进行的调用甚至不会达到这个目的。道德:不要从构造函数调用虚函数。

    我认为最干净的方法是进行两阶段建设。一个对对象进行基本连接的构造函数和一个必须在使用它之前调用的init()方法。客户端代码(componentholder?)无法在所有对象完全构造后调用此init。

        3
  •  0
  •   Ralph    15 年前

    为什么start()方法需要是虚拟的?

    可以使其非虚拟化并实现派生的构造函数 这样地:

    SpecializedComponent::SpecializedComponent() {
        m_address = getAddressFromParameterFile("SpecializedComponent");
        start();
    }
    

    这比在对象完全 构造,因为两步构造容易出错。(如果你这样做了 需要两步施工,考虑工厂(或工厂方法)来 确保只存在完全构造的对象。建造师 私人和工厂(方法)是朋友。)

    另一种方法是将地址的计算移出 对象构造。这将导致如下代码:

    SpecializedComponent::SpecializedComponent(const std::string& address)
     : Component(address)
    {}
    
    Component::Component(const std::string& address)
     : m_address(address)
    {
        start();
    }
    

    这种方法提高了派生的 专用组件,因为它消除了对 参数文件。

    为了方便起见,可以向实例提供静态工厂方法 您的专业组件:

    SpecializedComponent* SpecializedComponent::create() {
        std::string address = getAddressFromParameterFile("SpecializedComponent");
        return new SpecializedComponent(address);
    }
    

    顺便说一句:考虑在组件文件夹中保存共享指针,而不是原始指针。

    推荐文章