59.有哪些情况必须用到成员列表初始化?作用是什么?
1.必须使用成员初始化的四种情况
① 当初始化一个引用成员时;
struct MyClass
{
const int mya;
int& myb;
MyClass(int a, int& b) :mya(a), myb(b) {}
~MyClass() {}
};
② 当初始化一个非静态的常量成员时;
int a = 1;
class MyClass
{
public:
const int mA;
MyClass():mA(a)// 在初始化列表初始化mA的值
{
}
};
③ 当调用一个基类的构造函数,而它拥有一组参数时;
#include<iostream>
#pragma warning(disable:4996)
using namespace std;
class BaseClass
{
public:
int basea;
int baseb;
public:
BaseClass(int ref1, int ref2): basea(ref1), baseb(ref2)
{
}
};
class DerivedClass : public BaseClass
{
public:
int derivedc;
public:
DerivedClass(int arg1, int arg2, int arg3) : derivedc(arg1), BaseClass(arg2, arg3) {} // 使用BaseClass的构造函数来初始化基类对象
};
int main()
{
int m = 5;
int n = 6;
int p = 7;
DerivedClass s(m, n, p);
cout << s.basea << endl;
cout << s.baseb << endl;
cout << s.derivedc << endl;
}
④ 成员类型是没有默认构造函数的类。
派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员;如果基类没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
则必须在派生类构造函数的初始化列表阶段显示调用
2.成员初始化列表做了什么
①初始化基类:如果类有一个基类,可以在成员初始化列表中使用基类的构造函数来初始化基类对象。
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
using namespace std;
#include <iostream>
using namespace std;
// 基类
class BaseClass
{
public:
BaseClass(int a, int b)
{
x = a;
y = b;
}
void printBaseClass() {
cout << "Base class: (" << x << ", " << y << ")" << endl;
}
protected:
int x;
int y;
};
// 派生类
class DerivedClass : public BaseClass
{
public:
DerivedClass(int a, int b, int c) : BaseClass(a, b)
{
z = c;
}
void printDerivedClass()
{
cout << "Derived class: (" << x << ", " << y << ", " << z << ")" << endl;
}
private:
int z;
};
int main()
{
DerivedClass derivedObj(1, 2, 3);
derivedObj.printBaseClass();
derivedObj.printDerivedClass();
return 0;
}
② 初始化成员变量:对于每个成员变量,可以使用成员初始化列表来指定其初始值。成员初始化列表中的顺序与成员变量在类中声明的顺序一致。
#include<iostream>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#pragma warning(disable:4996)
using namespace std;
class MyClass
{
public:
MyClass() : member1(0), member2("default"), member3(123) {} // 使用成员初始化列表初始化成员变量
void printMyClass()
{
cout << "Obj.member1 = " << this->member1 << ", "
<< "Obj.member2 = " << this->member2 << ", "
<< "Obj.member3 = " << this->member3 << endl;
}
private:
int member1;
std::string member2;
double member3;
};
int main()
{
MyClass Obj;
Obj.printMyClass();
return 0;
}
③默认参数:如果成员变量有一个默认参数,可以在成员初始化列表中使用默认参数来初始化成员变量。
class MyClass
{
public:
MyClass(int arg1, int arg2 = 0) : member1(arg1), member2(arg2) {} // 使用默认参数来初始化成员变量
private:
int member1;
int member2;
};
需要注意的是,如果类中没有明确定义构造函数,则编译器会生成一个默认构造函数。在这个默认构造函数中,成员初始化列表中的值将被忽略,而成员变量将被初始化为默认值。此外,在使用成员初始化列表时,需要确保列表中的类型与成员变量的类型匹配,否则将导致编译错误。