初始化类层次结构中的变量

时间:2014-07-16 16:56:40

标签: c++ class oop inheritance design-patterns

我被分配了清理班级层次结构的任务,但我陷入了一种困境。我现在留下的东西大致如下:

class Base
{
Base() = 0;

function1();
   ...
function5();

protected:

int variable1_;
   ...
int variable10_;
}; 

class DerivedOne
   : public Base
{
   DerivedOne() = 0;

   function6();
      ...
   function10();

 protected:

   int variable11_;
      ...
   int variable20_;
};

class DerivedTwo
   : public DerivedOne
{
    DerivedTwo()
       : DerivedOne() 
    {
       ... Fill variable1_ to variable25_ with data read from file ...
       variable1_ = ...
    }

    function11();
      ...
    function15();

  private:

    int variable21_;
      ...
    int variable25_;
};

因此,在DerivedTwo中为25变量分配了它们的值,这样就很容易出错。当另一个类继承自DerivedOne时,几乎可以肯定该人将忘记初始化其中一个变量。

我一直在玩这种层次结构的不同方式,但没有什么感觉真的。

我理解在不知道这些类实际做什么的情况下很难说出具体的东西,但我有兴趣知道这个设计是否存在根本性的错误,或者我是否忽略了一些优雅的初始化方法所有的变数。

2 个答案:

答案 0 :(得分:1)

推导的原则是首先构造基础对象,然后构造基础对象。这需要Base和DerivedOne构造函数自己生成一个有效的对象。

构建DerivedTwo时,您的代码清楚地表明了这一点:

   DerivedTwo()
       : DerivedOne()  // First the base object constructor is called, before anything else 
   {
       // then remaining initialisation, after DerivedOne() was created
   }

因此每个类至少应该将自己的变量初始化为一个初始的有效状态,它自己的函数可以以一致的方式处理它。

Base() : variable1_(/*default value here*/), variable10_(/*default value here*/) {}
Base(int v1, int v10) : variable1_(v1), variable10_(v10) {} // for convenience

之后,一个派生类可能会覆盖其基类的变量。使用getter / setter当然会更安全,更优雅,但还可以。

如果你采用这种设计,如果一个子类来源忘记初始化其父变量之一,这不应该导致灾难,因为至少基础对象是以一种体面的方式初始化的。

现在问题是您还通过读取文件来启动DerivedTwo。记住,首先创建Base,然后创建DerivedOne,然后只有DerivedTwo读取值。当文件无法读取或不一致时会发生什么?除非抛出异常,否则最终可能会出现一个不一致的对象。所以你必须管理它并确保DerivedTwo处于稳定状态:

   DerivedTwo()
       : DerivedOne()  // First the base object constructor is called 
   {
       // then initialise all own members to a consitent state
       // then try to read the file and manage potential errors 
   }

答案 1 :(得分:0)

每个班级都应负责初始化自己的数据成员。如您所述,Base假设DerivedX将初始化其数据成员是危险的。所以......

Base应初始化variable1_ ... variable10_

DerivedOne应初始化variable11_ ... variable20_

DerivedTwo应初始化variable21_ ... variable25_

......等等。

当然,这并没有解决为什么课程以这种方式布局的问题......