为什么子类的初始化列表不能初始化父类的成员
- C++初始化列表是一种效率更高的初始化方法,但也有一些不能使用的场景。
举个例子
- 以下定义一个矩形,然后再定义一个正方形,继承自矩形。
- 这段代码有问题吗?
...
class Rectangle{
public:
Rectangle() :a(0), b(0){}
Rectangle(int x, int y) :a(x), b(y){}
public:
int a;
int b;
};
class Square :public Rectangle
{
public:
Square(int x):a(x) {}
};
...
error C2614: “Square”: 非法的成员初始化:“a”不是基或成员
- 虽然乍一看没毛病,继承是public继承,构造是父类先构造,但为什么子类用初始化列表时会报错呢?
- 而将子类的构造函数改成下面这样,竟然就可以了。它们明明看起来一样啊?
...
Square(int x)
{
a = x;
}
...
查找原因
- 这就要探讨以下初始化列表和普通初始化的区别。
- 编译器在检查列表初始化时,大概经过了这样一个过程:
子类:来来来,父类,你先构造
父类:好,我的成员a和b还没定义,那就用初始化列表(int a=0,int b=0)来初始化,构造完毕。
子类:轮到我构造了,我的成员里没有a,我也用的是初始化列表(int a=x),所以我也来int a=x,咦,好像不对,我的成员里没有a啊?(可是如果父类里a我继承的话,为什么主人要用初始化列表(int a=x)再来定义一次a呢?)
- 编译器不知道怎么处理了,只能告诉你,这个语法不对。
- 而将子类初始化放在构造函数内部,则是这样一个过程:
子类:来来来,父类,你先构造
父类:好,我的成员a和b还没定义,那就用初始化列表(int a=0,int b=0)来初始化,构造完毕。
子类:轮到我构造了,我用的是赋值初始化(a=x),当然也要先看下有没有a,正好有(从父类继承的),执行a=x,初始化好了。
- 看到不同了吗?在构造时,初始化列表会将成员定义和赋值优化到一步里。这正是为何无法使用子类初始化列表初始化父类成员,也是初始化列表效率高的原因,因为初始化列表节省了一步操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】