简体   繁体   English

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

[英]Initializing variables in a class hierarchy

I got assigned the task to clean up a class hierarchy, but I'm stuck in a bit of a rut. 我被分配了清理类层次结构的任务,但是我陷入了困境。 I'm now left with something that roughly looks like this: 我现在剩下的东西大概是这样的:

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_;
};

So 25 variable are assigned their values in DerivedTwo, making it easy to make a mistake. 因此,在DerivedTwo中为25个变量分配了它们的值,因此很容易出错。 When another class inherits from DerivedOne, it's almost certain that that person will forget to initialize one of the variables. 当另一个类继承自DerivedOne时,几乎可以肯定的是,那个人会忘记初始化变量之一。

I've been playing around with different ways of designing this hierarchy, but nothing really feels right. 我一直在尝试使用不同的方法来设计此层次结构,但是没有什么感觉真的对。

I understand it's difficult to say something concrete without knowing what these classes actually do, but I would be interested in knowing if there is something fundamental wrong with this design, or if I have overlooked some elegant way of initializing all the variables. 我知道在不了解这些类的实际作用的情况下很难说出具体的东西,但是我想知道这种设计是否存在根本性的错误,或者是否忽略了初始化所有变量的优雅方法。

The principle in derivation is that base object is constructed first, and the derived afterwards. 派生的原理是先构造基础对象,然后构造派生对象。 This requires the Base and DerivedOne constructor to produce a valid object on its own. 这要求Base和DerivedOne构造函数自行产生一个有效的对象。

When constructing DerivedTwo, your code makes this clear: 在构造DerivedTwo时,您的代码应明确说明:

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

So each class should at least initialise its own variables to an initial valid state that its own functions can handle in a consistent manner. 因此,每个类至少应将其自己的变量初始化为一个初始有效状态,该状态可以由其自己的函数以一致的方式处理。

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

One derived class could overwrite variables of its base class afterwards. 之后,一个派生类可以覆盖其基类的变量。 It would of course be safer and more elegant to use getters/setters, but its ok. 使用getter / setter方法当然会更安全,更优雅,但是还可以。

If you adopt this design, if one subderived class forgets to initialise a variable one of its parents, this should not lead to a catastrophee because at least the base object is initialised in a decent manner. 如果采用这种设计,则如果一个派生类忘记初始化其父级变量之一,则不应导致灾难,因为至少基础对象是以体面的方式初始化的。

Now the problem is that you also initiate your DerivedTwo by reading a file. 现在的问题是,您还可以通过读取文件来初始化DerivedTwo。 Remember, first Base is created, then DerivedOne, and then only DerivedTwo reads the values. 记住,首先创建Base,然后创建DerivedOne,然后只有DerivedTwo读取值。 What happen when the file cannot be read or is unconsistent ? 当无法读取文件或文件不一致时会发生什么? You might end up having an inconsistent object, unless your throw an exception. 除非抛出异常,否则您最终可能会遇到一个不一致的对象。 So you have to manage this and make sure that DerivedTwo is in a stable state: 因此,您必须对此进行管理,并确保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 
   }

Each class should be responsible for initializing its own data members. 每个类都应负责初始化其自己的数据成员。 As you identified, it is dangerous for Base to assume that DerivedX will initialize its data members. 如您DerivedXBase假设DerivedX将初始化其数据成员是危险的。 So... 所以...

Base should initialize variable1_ ... variable10_ Base应初始化variable1_ ... variable10_

DerivedOne should initialize variable11_ ... variable20_ DerivedOne应该初始化variable11_ ... variable20_

DerivedTwo should initialize variable21_ ... variable25_ DerivedTwo应该初始化variable21_ ... variable25_

...and so on. ...等等。

Of course, this doesn't address the question of why the classes are laid out in such a fashion... 当然,这并没有解决为什么类以这种方式进行布局的问题...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM