缘由

偶尔编写如下代码,编译出错,

class Base{public:int x;
};class Derived : public Base {public:Derived() : x(10) {cout << "Derived " << x << endl;};int y;
};int main()
{Base *p = new Derived();
}

错误:

D:\CLionProjects\Demo\main.cpp: In constructor ‘Derived::Derived()’:
D:\CLionProjects\Demo\main.cpp:45:17: error: class ‘Derived’ does not have any field named ‘x’
Derived() : x(10) {

错误是子类的构造方法的初始化列表中无法初始化父类成员变量。那么是为什么呢?本文从如下几个方面进行思考讨论?

  1. 初始化列表为何物,为何要在初始化列表中初始化变量?
  2. 初始化列表,构造函数的执行顺序如何?
  3. c++ 子类 父类的对象模型是如何的?

初始化列表为何物,为何要在初始化列表中初始化变量?

当我们定义变量时习惯于对其进行初始化,而非先定义,再赋值:

string foo = "Hello World!";  // 定义并初始化
string bar;                   // 默认初始化为空string对象
bar = "Hello World!";         // 为bar赋一个新值。

就对象的数据成员而言,初始化和赋值也有类似的区别,如果没有在构造函数的初始化列表中显示地初始化成员,则该成员将在构造函数体之前执行默认初始化,例如:

class Demo {public:Demo(string name) {  // 此处隐式的对name进行了初始化this->name = name; // 此处是赋值,并非初始化};
private:string name;
};

有很多地方强调要使用初始化列表进行变量的赋值,为何呢?个人汇总如下:

  1. 效率问题,未使用初始化列表进行赋值,会调用默认构造方法(对于对象而言,对于进本变量则是赋初值)初始化,然后再使用operator=进行赋值。
  2. 有些变量没有默认的构造方法,比如自定义的类(显示的定义了构造方法)。
  3. 有些变量只能在初始化时赋值,不在再更改,比如const变量。
  4. 引用变量只能在初始化时赋值。

初始化列表,构造函数的执行顺序如何?

正如上面所述,初始化列表是在构造函数体之前执行:

struct P {P(){cout << "P construct" << endl;};
};
class Base {public:Base():p(P()){cout << "Base construct" << endl;};P p;
};int main()
{Base p;
}

运行结果:

P construct
Base construct

执行顺序:父类初始化列表-> 父类构造函数->子类初始化列表->子类构造函数。

c++ 子类 父类的对象模型是如何的?

class Base {public:int x;
};class Derived :: Base {public:int y;
};int main()
{Base *base = new Derived();
}

总结

猜测可能是如下原因:

  1. 子类的初始化列表,只能对子类的成员变量进行初始化,也就是Derived::x(自己类的作用域),所以报子类无该变量的错误。
  2. 因为首先调用了父类的默认构造方法,在这之前,执行父类的初始化列表对x进行了初始化,如果子类还可以对x进行初始化,那么就会对x进行两次初始化;编译器不允许行为;

个人倾向于编译行为,不能再子类的初始化列表显示的父类的成员变量进行初始化;如果需要,在初始化列表中包含父类的相应构造方法(含有初始化列表)。

子类初始化列表不能初始化父类元素 -- class 'Derived' does not have any field named 'x'相关推荐

  1. 为什么不能在子类的初始化列表里初始化父类的成员

    好几次遇到此类问题了:便不得不找些资料弄明白它: 具体代码是: 2 3 4 5 6 7 8 9 10 class A { protected:     int n_; }; class B : pub ...

  2. C++必须使用【初始化列表】初始化数据成员的三种情况

    类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员: 2.进入构造函数后在构造函数中执行一般赋值与计算. 使用初始化列表有两个原因: 原因1.必须这样做: < ...

  3. 28.构造函数中,成员变量一定要通过初始化列表来初始化的?

    首先要明确:如果对象成员是const或者引用的话,必须将其初始化! 构造函数中,成员变量一定要通过初始化列表来初始化的的几种情况! 1)对象成员是const或者引用 #include <iost ...

  4. C++经典问题:如果对象A中有对象成员B,对象B没有默认构造函数,那么对象A必须在初始化列表中初始化对象B?

    对象成员特点总结: (1)实例化对象A时,如果对象A有对象成员B,那么先执行对象B的构造函数,再执行A的构造函数. (2)如果对象A中有对象成员B,那么销毁对象A时,先执行对象A的析构函数,再执行B的 ...

  5. C++类构造函数初始化列表及初始化成员变量的误区

    构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: [cpp] view plaincopy class CExample { pub ...

  6. [面试] C++ 语法(一) —— 初始化列表的初始化顺序

    首先来看一道经典的 C++ 面试题: (1)初始化列表的初始化顺序:不是按照列表的顺序进行的 (2)初始化列表的初始化顺序:是按照内存模型中的成员变量的顺序(也即类声明的定义顺序)进行的: (3)也即 ...

  7. 构造函数中,成员变量一定要通过初始化列表来初始化的几种情况(转载)

    1.参考博客 博客链接1 博客链接2 2.实例如下 class A { ... private:int a; }; class B : public A { ... private:A &aa ...

  8. C++成员变量初始化列表中初始化顺序

    1.C++使用初始化列表初始化时,成员变量的初始化顺序:只与定义变量的顺序有关. #include <iostream> using namespace std; class A{ pri ...

  9. 初始化列表的初始化顺序

    构造函数初始化列表仅用于初始化成员的值,并不指定这些初始化执行的次序.成员被初始化的次序就是定义成员的次序.第一个被定义的成员先被初始化,依次类推.一般,初始化的顺序无关紧要,然而,如果一个成员是根据 ...

最新文章

  1. RDKit | 基于RDKit绘制带原子索引的分子
  2. vue方法调用失败后多次调用_浅析Vue中 computed / watch / methods的区别
  3. 华为手机服务器响应,服务器响应优化
  4. 【Tika基础教程之一】Tika基础教程
  5. iOS事件机制(一)
  6. 不常用却很有妙用的事件及方法
  7. 微信公众号从入门到入坑
  8. 游戏开发所需要看的书
  9. 深入浅出学习CAN系列-了解CAPL编程语言
  10. 青年教师计算机培训美篇,小学生停课不停学美篇 小学生停课不停学美篇开头语...
  11. perl data::dumper 模块使用
  12. 基于51单片机的智能大棚光温控制系统
  13. 2020年黑龙江省大豆种植分布数据
  14. 客户端监控要怎么做?
  15. 精通Dubbo——Dubbo支持的协议的详解
  16. P1287 盒子与球题解【python】
  17. Unsplash能找到很多免费无版权图片
  18. MFC打开一个文件方法汇总
  19. 用java画爱心图_用java实现 图片组成心形图案
  20. java gmail smtp_使用Javamail连接到Gmail smtp服务器会忽略指定的端口,并尝试使用25...

热门文章

  1. LILO使用指南(中)
  2. websocket客户端和服务器开发总结
  3. keil5的界面认识
  4. cve 漏洞编号 申请流程
  5. 手机 听广播 不用 耳机 android,无需插入耳机即可收听FM广播的高级提示
  6. 老年人养生:有意识的进行左手摇蒲扇 有助于预防脑溢血 健康养生
  7. Global Pointer
  8. 如何在安卓APP中添加分享按钮?
  9. MATLAB当中线性方程组、不定方程组、奇异方程组、超定方程组的介绍
  10. 2020年教师计算机培训计划,2019-2020年年教师培训计划.docx