如何在成员初始化列表中传递类成员的指针?

时间:2016-08-10 21:05:08

标签: c++ object initialization-list member-initialization

我有一个名为HighWaterDetector的类:

class HighWaterDetector
{
public:
    HighWaterDetector(Device* device);
    Device * devicePtr;
    Output * output1Ptr;
    CloudMsgParser * cloudMsgParserPtr;
    Output output1;
    NCD2Relay ncd2Relay;
    CloudMsgParser cloudMsgParser;
};

使用构造函数:

HighWaterDetector::HighWaterDetector(Device* device): ncd2Relay(), output1(1, &ncd2Relay){
}

我正在尝试在HighWaterDetector的成员初始化列表中初始化Output的实例,但是输出需要您将指针传递给NCD2Relay的实例,NCD2Relay也是类HighWaterDetector的成员。我的程序在输出构造函数内崩溃。这是错误的做法吗?我做错了什么?

输出类:

class Output
{
public:
    Output(ushort relayNum, NCD2Relay* ncd2RelayPtr);
    ushort relayNum;
    OutputStatus outputStatus;
    int setOutputOn(void);
    int setOutputOff(void);
    void process(void);
    NCD2Relay* ncd2RelayPtr;
};


//Output Constructor
Output::Output(ushort relayNum, NCD2Relay* ncd2RelayPtr) {
    this->relayNum = relayNum;
    this->ncd2RelayPtr = ncd2RelayPtr; //DOESNT CRASH IF I COMMENT THIS OUT
    this->outputStatus.outFail = 0;
    Serial.print("Initializing output ");
    Serial.println(this->relayNum);
    this->setOutputOff();
}

2 个答案:

答案 0 :(得分:4)

您是否注意到编译器警告?或者他们是否最大化? 您的成员的声明顺序可能是原因:

class HighWaterDetector
{
public:
    HighWaterDetector(Device* device);
    Device * devicePtr;
    Output * output1Ptr;
    CloudMsgParser * cloudMsgParserPtr;
    Output output1;                     // <- This is constructed before
    NCD2Relay ncd2Relay;                // <- This...
    CloudMsgParser cloudMsgParser;
};

但你的构造函数如下:

HighWaterDetector::HighWaterDetector(Device* device): ncd2Relay(), output1(1, &ncd2Relay){ ... }

在上面的上下文中,在ncd2Relay的构造函数中使用output1的地址只是使用指向未初始化对象的指针,当您最终在构造之前取消引用它时,该指针是未定义行为。因此,您需要在类定义中强制执行排序......

引用C ++标准:(强调我的)[class.base.init/13]

  

在非委托构造函数中,初始化继续进行   以下顺序:

     
      
  • 首先,仅针对派生程度最高的类([intro.object])的构造函数,按顺序初始化虚拟基类   它们出现在深度优先的从左到右的遍历中   基类的非循环图,其中“从左到右”是基数的顺序   派生类中基类的外观   基说明符列表。

  •   
  • 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论顺序如何)   MEM-初始化)。

  •   
  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样无论顺序如何   MEM-初始化)。

  •   
  • 最后,执行构造函数体的复合语句。

  •   

答案 1 :(得分:3)

在C ++中,初始化列表不遵循您在初始化程序中编写项目的顺序。它遵循在您的班级中声明成员的顺序。由于您将NCD2Relay放在班级Output之后,NCD2Relay将在输出后初始化,即使在初始值设定项中NCD2Relay也是如此首先因此,只需在您的类声明中的NCD2Relay之前移动Output