为什么子类需要调用父类的构造函数 ?

因为长时间没有写过继承相关的代码,竟然忘记子类需要给父类初始化成员,即调用父类的构造函数初始化继承过来的成员变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 基类
MsgNode::MsgNode(char* msg, int max_len)
: cur_len_(0)
, total_len_(max_len + HEAD_LENGTH)
{
data_ = new char[total_len_ + 1]();
// 暂时封装为 头部+数据
memcpy(data_, &max_len, HEAD_LENGTH);
memcpy(data_ + HEAD_LENGTH, msg, max_len);
data_[total_len_] = '\0';
}

MsgNode::MsgNode(int max_len)
: cur_len_(0)
, total_len_(max_len)
{
data_ = new char[total_len_ + 1]();
}

// 派生类
RecvNode::RecvNode(int max_len, int msgID)
: MsgNode(max_len)
, msgID_(msgID)
{

}

// 派生类
SendNode::SendNode(const char* msg, short max_len, short msgID)
: MsgNode(max_len + HEAD_LENGTH)
, msgID_(msgID)
{

}

子类对象包含父类部分,必须确保父类部分被正确初始化。否则,父类的数据成员可能会处于未定义状态,从而导致程序错误或不稳定。通过调用父类构造函数,可以重用父类中已有的初始化逻辑,避免在每个子类中重复编写相同的初始化代码。如果父类的构造函数有某些重要的初始化操作,这些操作需要在任何子类对象创建时都执行,以确保一致的行为。

  • 父类构造函数无参:如果父类提供了一个无参构造函数,子类构造函数可以不显式调用它。编译器会自动调用它
  • 父类构造函数有参数:如果父类构造函数需要参数,子类必须在其构造函数的初始化列表中显式调用父类的构造函数,并传递适当的参数