【C/C++】构造函数、默认构造函数、成员初始化列表

常见问题

Q1. 下列关于构造函数的描述中,错误的是( )

A. 构造函数可以设置默认的参数

B. 构造函数在定义类对象时自动执行

C. 构造函数可以是内联函数

D. 构造函数不可以重载

Q2. 下列代码中a、b的各个成员变量值是多少?

 1 class Student
 2 {
 3 public:
 4     Student() {}
 5     void show();
 6 private:
 7     string name;
 8     int number;
 9     int score;
10 };
11 Student a;
12 int main()
13 {
14     Student b;
15 }

Q3. 运行下面的C++代码,其输出结果是什么?

 1 #include <iostream>
 2 using namespace std;
 3 class A
 4 {
 5 private:
 6     int i;
 7     int j;
 8 public:
 9     A() : j(0), i(j+2) {}
10     void print()
11     {
12         cout << "i: " << i << ", j: " << j << endl;
13     }
14 };
15 int main()
16 {
17     A a;
18     a.print();
19     return 0;
20 }

构造函数、成员初始化列表

1. 构造函数

  构造函数是特殊的成员函数,与其他成员函数不同,构造函数和类同名,而且没有返回类型。一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参。

2. 默认构造函数

  如果没有为一个类显式定义任何构造函数,编译器将自动为这个类生成默认构造函数。默认构造函数是不带参数的构造函数,或所有的形参都有默认实参的构造函数。

  若使用编译器自动生成的默认构造函数(或自己定义一个未进行任何操作的默认构造函数),则类中的每个成员,例用与初始化变量相同的规则来进行初始化。

  (1) 类成员:运行该类型的默认构造函数来初始化。

  (2) 内置或复合类型的成员初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中它们被初始化为0。

  实际上,如果定义了其他构造函数,则提供一个默认构造函数几乎总是对的。

3. 成员初始化列表

  在冒号和花括号之间的代码称为构造函数的初始化列表。构造函数的初始化列表为类的一个或多个数据成员指定初值。它跟在构造函数的形参表之后,以冒号开始。构造函数的初始化式是一系列成员名,每个成员后面是括在圆括号中的初始值。多个成员的初始化用逗号分隔。

  在C++中,成员变量的初始化顺序与变量在类型中的声明顺序相同,而与它在构造函数的初始化列表中的顺序无关。

  省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。从概念上讲,可以认为构造函数分两个阶段执行:

  (1) 初始化阶段;

  (2) 普通计算阶段。计算阶段由构造函数体中的所有语句组成。

  不管成员函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化(调用默认构造函数初始化,若没有默认构造函数,则编译错误),内置和复合类型的成员,只对定义在全局作用域中的对象才初始化,定义在局部作用域中的对象包含的内置(如int等类型)和复合(如数据、指针等类型)类型的成员没有初始化。

  因为内置类型的成员不进行隐式初始化,所以对这些成员是进行初始化还是赋值无关紧要。但对于类类型的数据成员若未在初始化列表显式初始化,而是在函数体里赋值,则相当于先调用类的默认构造函数进行初始化,再在函数体中赋值,故相比于直接利用初始化列表,效率较低。

  必须使用成员初始化列表的情况如下:

  有些数据成员必须在构造函数的初始化列表中进行初始化。对于这样的成员,在构造函数体内对它们赋值是不起作用的。没有默认构造函数的类类型的成员,以及const类型的成员变量和引用类型的成员变量,都必须在构造函数初始化列表中进行初始化。

时间: 2024-12-28 01:26:44

【C/C++】构造函数、默认构造函数、成员初始化列表的相关文章

C++类的成员初始化列表的相关问题

在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量对象(const member); 3,调用一个基类的构造函数,且该基类的构造函数有一组参数: 4,调用一个成员类(member class)的构造函数,且该构造函数有一组参数 这四种情况程序可以正常编译,但是效率有所欠缺(下面会具体说到). class Word{ String _name; in

成员初始化列表的使用及特点

成员初始化列表:用于辅佐构造函数(可以是默认构造函数),对成员变量进行赋值. 一般情况下,使用成员初始化列表与在构造函数内部对成员进行赋值没有什么好坏之分,使用哪种方式对对象进行初始化全凭心情. 但是,在以下四种情况的成员变量中,只能使用成员初始化列表进行初始化: 1.当初始化一个const member时.这种情况不用多说,对于const变量的初始化只能使用初始化列表,而不能在constructor中进行赋值,不然违背成员变量const的性质. 2.当初始化一个reference member

C++对象模型——成员初始化列表(第二章)

2.4    成员初始化列表 (Member Initialization List) 当编写一个类的构造函数时,有可能设定类成员的初始值,或者通过成员初始化列表初始化,或者在构造函数内初始化,除了四种情况,其实任何选择都差不多. 本节中,首先澄清何时使用初始化列表才有意义,然后解释初始化列表内部的真正操作是什么,然后再看一些微妙的陷阱.  下列情况中,为了让程序能够被顺利编译,必须使用成员初始化列表(不能在构造函数内初始化): 1.    当初始化一个引用的成员时 2.    当初始化一个常量

c++类 用冒号初始化对象(成员初始化列表)

c++类 用冒号初始化对象(成员初始化列表) 成员初始化的顺序不同于它们在构造函数初始化列表中的顺序,而与它们在类定义中的顺序相同 #include<iostream> int n=0; using namespace std; class Cbox{ int a ; int b ; int c ; public: int g ; Cbox():a(n++),c(n++),b(n++){} ~Cbox(){cout<<a<<" "<<b&

C++:用成员初始化列表对数据成员初始化

1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Complex(double r,double i) //声明构造函数原型 { ........... } }; Complex::Complex(double r,double i) //在构造函数中用赋值语句对数据成员赋初值 { real = r; imag = i; } 2.另一种初始化数据成员的

构造函数调用构造函数进行数据成员初始化问题(极易出错)

先看下面代码: #include<iostream> using namespace std; class CLS { public: int m_i; CLS(int i):m_i(i) { cout<<"CLS():this="<<this<<endl; } CLS() { CLS(0); cout<<"CLS():this="<<this<<endl; } }; int mai

C++学习之路: 构造函数详解与初始化列表

引言:这是C++对象内存分配的基础,为防止忘记. 看一个类包含其他类时是如何构造的. #include <iostream> using namespace std; class Object { public: Object() { cout << "Object.." << endl; } ~Object() { cout << "~Object.." << endl; } }; class Conta

构造函数——默认构造函数

每个类分别定义了他的对象被初始化的方式,这些控制其对象初始化的成员函数就叫构造函数. 和其他函数的区别是:1.构造函数没有返回值.2.不能被声明成const,因为创建一个const对象时,知道构造函数完成初始化的过程,对象才能真正取得其“const“属性,所以构造函数在const对象的构造过程中是可以向其写值的. 当一个类没有定义构造函数的时候,编译器会隐式的合成一个构造函数,称为“合成的默认构造函数”.初始化顺序是先用类内的初始值初始化他,没有初始值的话执行默认初始化.注意只有在没有定义任何构

C++成员初始化列表

class A { public: A() { cout << "class A default constructor called" << endl; a = 0; } A(int param) { cout << "class A constructor called" << endl; a = param; } ~A() { } virtual void FunctionA() { cout <<