C++ MyBook构造函数Book(t,a)初始化列表作用及等价写法
C++子类构造函数初始化列表说明
你问的这行是C++构造函数的初始化列表语法,是面向对象继承场景下的标准写法,下面分部分讲清楚含义、作用和等价写法。
语法与作用拆解
你看到的完整代码段是:
MyBook(string t,string a,int price):Book(t,a){ this->price = price; }
逐部分解释:
- 前半段
MyBook(string t,string a,int price)是子类MyBook的构造函数签名,规定创建MyBook实例时需要传入书名、作者、价格三个参数。 - 冒号后面的
Book(t,a)是初始化列表的核心逻辑:在执行MyBook构造函数内部的代码之前,先调用父类Book的双参数构造函数,把传入的书名t、作者a传给父类,完成父类部分的成员初始化。 - 大括号内的
this->price = price是MyBook自己的逻辑,用来初始化子类独有的价格成员。
这种写法是C++的强制要求:你定义的Book类只实现了需要两个入参的构造函数,没有无参构造。创建子类实例时必须先完成父类部分的初始化,如果你不手动在初始化列表里指定调用父类的双参构造,编译器会默认尝试调用父类的无参构造,直接触发编译错误。
从封装角度讲这种写法也更合理:title、author是Book类的成员,理应由Book自己的构造函数负责初始化,子类不需要重复实现父类成员的赋值逻辑,后续如果Book类修改了这两个字段的初始化规则,子类代码不需要跟着改动。
等价实现写法
以下写法运行效果和原代码一致,但除了优化写法外,其余都存在设计缺陷,仅做语法演示,实际开发优先用原有的初始化列表写法。
写法1:给父类补充无参构造,在子类构造函数体内直接给父类成员赋值
class Book{ protected: string title; string author; public: // 新增无参构造,让编译器能默认调用 Book(){} Book(string t,string a){ title=t; author=a; } virtual void display()=0; }; class MyBook : Book{ private: int price; public: // 不再通过初始化列表调用父类构造,直接在函数内给父类protected成员赋值 MyBook(string t,string a,int price){ title = t; author = a; this->price = price; } virtual void display(void) override { cout << "Title: " << title << endl; cout << "Author: " << author << endl; cout << "Price: " << price << endl; } };
这种写法的问题是破坏了封装边界:父类成员的初始化逻辑本该由父类控制,子类直接越权赋值,后续如果Book类给title、author加了非空校验、长度限制之类的逻辑,子类的赋值代码会直接绕过这些校验,引发bug。
写法2:将子类自身成员也放入初始化列表(推荐的优化写法,和原代码完全等价)
初始化列表不仅可以调用父类构造,也可以直接初始化自身成员,比在函数体内赋值效率更高(省去了成员默认构造后再赋值的额外开销):
// 直接把price也放进初始化列表,函数体不需要再写赋值逻辑 MyBook(string t,string a,int p):Book(t,a), price(p){}
这种写法是工业界更推荐的规范写法,和你看到的原写法逻辑完全一致,只是更简洁。
内容的提问来源于stack exchange,提问作者Abu Sayed
相关产品推荐
相关产品推荐

