一、类对象作为成员变量时的构造函数问题




1、问题描述


如果 一个类 A 的对象 作为 另外一个类 B 的成员变量时 ,

在以下场景会报错 :

  • 为类 A 定义 有参的 构造函数 , 那么 A 的无参默认构造函数就失效了 ;
  • 此时使用 默认无参构造函数 初始化 B , 就会报错 ;

在一个类中 , 其成员变量是 带有参构造函数 的类型 , 这种情况下没有调用 有参构造函数的机会 , 此时就会出现 编译报错情况 ;


在下面的代码中 , A 只有通过 有参构造函数 A(int age, int height) 进行初始化 , 无法再使用 无参构造函数 ;

class A
{
public:
	// 带参构造函数
	A(int age, int height)
	{
	}

public:
	int m_age;		// 年龄
	int m_height;	// 身高
};

在 B 中 , 如下声明 A 成员变量 , 只能调用 A 的 无参构造函数创建 A 对象 , 但是 A 的 无参构造函数无法使用 , 必须使用 A 的有参构造函数 , 这里就出现问题 , 报错 “B::B(void)”: 由于 数据成员“B::m_a”不具备相应的 默认构造函数 或重载解决不明确,因此已隐式删除函数 ;

class B
{
public:
	int m_age;		// 年龄
	A m_a;			// A 类型成员变量
};

解决上述问题的方案 就是 C++ 中的 构造函数 初始化列表 ;


2、错误代码示例


代码示例 :

#include "iostream"
using namespace std;

class A
{
public:
	// 带参构造函数
	A(int age, int height)
	{
	}

public:
	int m_age;		// 年龄
	int m_height;	// 身高
};

class B
{
public:
	int m_age;		// 年龄
	A m_a;			// A 类型成员变量
};


int main()
{
	// 通过 B 的默认无参构造函数初始化 B 对象
	B b;


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
}

执行结果 :

已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>hello_world.cpp
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\hello_world.cpp(28): error C2280:B::B(void): 尝试引用已删除的函数
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\hello_world.cpp(22): message : 编译器已在此处生成“B::B”
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\hello_world.cpp(22,1): message :B::B(void): 由于 数据成员“B::m_a”不具备相应的 默认构造函数 或重载解决不明确,因此已隐式删除函数
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\hello_world.cpp(21): message : 参见“B::m_a”的声明
1>已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0==========

【C++】构造函数初始化列表 ① ( 类对象作为成员变量时的构造函数问题 | 构造函数初始化列表语法规则 )-LMLPHP





二、构造函数初始化列表




1、构造函数初始化列表语法规则


在 C++ 语言中 , 构造函数初始化列表 是一种用于初始化类的成员变量的方法 ;


构造函数初始化列表 可实现功能 :

  • 为成员变量提供初始值
  • 调用其他 成员变量的 构造函数 来初始化成员变量

构造函数初始化列表语法规则 :

构造函数() : 成员变量名称(成员变量值) , 成员变量名称(成员变量值) 
{
	// 构造函数内容
}
  • 构造函数初始化列表 位置在 构造函数 的 参数列表之后 , 冒号 : 与花括号 {} 之间 ;
  • 使用 逗号 , 分隔 ;
  • 初始化列表中的元素由 成员变量的名称 和 初始值组成 , 使用等号 = 连接 ;

在下面的代码中 , 为 B 类定义了默认的构造函数 , 其中定义了 构造函数 初始化列表 ;

在 初始化列表中 ,

  • m_age(10) 是 为 m_age 提供了初始值 ;
  • m_a(10, 150) 是 调用了 A 的有参构造函数 ;

代码示例 :

class B
{
public:
	B() : m_age(10) , m_a(10, 150)
	{}
public:
	int m_age;		// 年龄
	A m_a;			// A 类型成员变量
};

2、代码示例 - 构造函数初始化列表语法规则


代码示例 :

#include "iostream"
using namespace std;

class A
{
public:
	// 带参构造函数
	A(int age, int height)
	{
		m_age = age;
		m_height = height;
	}

public:
	int m_age;		// 年龄
	int m_height;	// 身高
};

class B
{
public:
	B() : m_age(10) , m_a(10, 150)
	{}
public:
	int m_age;		// 年龄
	A m_a;			// A 类型成员变量
};


int main()
{
	// 通过 B 的默认无参构造函数初始化 B 对象
	B b;


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
}

执行结果 :

【C++】构造函数初始化列表 ① ( 类对象作为成员变量时的构造函数问题 | 构造函数初始化列表语法规则 )-LMLPHP

09-19 14:14