文章目录
- 一、构造函数分类
- 1、构造函数分类简介
- 2、构造函数分类代码分析
- 无参构造函数
- 有参构造函数
- 拷贝构造函数
- 二、代码示例 - 三种类型构造函数定义与调用
一、构造函数分类
1、构造函数分类简介
C++ 构造函数可以分为以下几类 :
- 无参构造函数 : 最简单也是默认的构造函数 , 函数没有参数 , 如果创建一个对象 , 没有传入参数 , 调用的就是该类型的 构造函数 ;
- 有参构造函数 : 带参数的 构造函数 , 创建 实例对象 时 , 为成员变量提供初始值 ;
- 拷贝构造函数 : 拷贝现有 实例对象 , 并以此拷贝的副本为数据 创建一个新的 实例对象 , 相当于创建了一个现有实例对象的副本 , 参数中包含 一个 相同类型 实例对象 引用 ;
2、构造函数分类代码分析
定义成员变量 : 下面的简介示例中是以该成员变量为基础进行赋值的 ;
public:
int m_age;
char* m_name;
无参构造函数
无参构造函数 : 只负责为指针类型的成员变量分配内存 , 并赋值一个初始值 , 没有具体的赋值信息 , 该初始化只能为 成员变量 赋值一个默认值 ;
// 无参构造函数
Student()
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if(m_name != NULL)
{
strcpy_s(m_name, 5, "name");
}
// 为 m_age 成员设置初始值
m_age = 0;
cout << "调用无参构造函数" << endl;
}
下面的代码 , 是自动调用无参构造函数 , 创建 实例对象 的方法 ;
// 调用无参构造函数
Student s1;
// 打印 Student s1 实例对象值
cout << "name : " << s1.m_name << " , age : " << s1.m_age << endl;
有参构造函数
有参构造函数 : 可以将 为 成员变量 赋值的数据放在 构造函数 参数中 , 传递进来 , 并在 构造函数 中 , 为 成员变量 赋值具体的值 ;
此处需要注意的是 , 这里传入的是 C 语言中的字符串 , 也就是 char * 类型的指针 , 传入后拷贝字符串时 , 需要判定字符串的长度 ;
// 有参构造函数
Student(int age, const char* name)
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if (m_name != NULL)
{
strcpy_s(m_name, length, name);
}
// 为 m_age 成员设置初始值
m_age = age;
cout << "调用有参构造函数" << endl;
}
下面的代码 , 使用了 2 种方法 , 手动调用了 有参构造函数 ;
// 调用有参构造函数
Student s2 = Student(18, "Tom");
// 打印 Student s1 实例对象值
cout << "name : " << s2.m_name << " , age : " << s2.m_age << endl;
有参构造函数有很多调用方法 , 下一篇博客详细分析每种调用方法的作用 ;
拷贝构造函数
拷贝构造函数 : 拷贝构造函数 也是 有参构造函数 中的一种 , 传入的是 相同类型的 常量引用 , 该引用指向的内容在函数内不可修改 ;
在 " 拷贝构造函数 " 中 , 主要读取 现有 实例对象 中每个 成员变量的值 , 将其赋值给 新创建的 实例对象 中的每个成员变量值 ;
新创建的 实例对象 , 与原来的 实例对象 只是值相同 , 数据地址完全不同 , 没有引用关系 ;
// 拷贝构造函数
Student(const Student& obj)
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if (m_name != NULL)
{
strcpy_s(m_name, sizeof(obj.m_name), obj.m_name);
}
// 为 m_age 成员设置初始值
m_age = obj.m_age;
cout << "调用拷贝构造函数" << endl;
}
二、代码示例 - 三种类型构造函数定义与调用
在下面的代码中 , 分别在 Student 类中定义了
- 无参构造函数
- 有参构造函数
- 拷贝构造函数
分别调用了上述三种类型的 构造函数 ;
完整代码示例 :
#include "iostream"
using namespace std;
class Student
{
public:
// 无参构造函数
Student()
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if(m_name != NULL)
{
strcpy_s(m_name, 5, "name");
}
// 为 m_age 成员设置初始值
m_age = 0;
cout << "调用无参构造函数" << endl;
}
// 有参构造函数
Student(int age, const char* name)
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if (m_name != NULL)
{
strcpy_s(m_name, sizeof(name), name);
}
// 为 m_age 成员设置初始值
m_age = age;
cout << "调用有参构造函数" << endl;
}
// 拷贝构造函数
Student(const Student& obj)
{
// 为 m_name 成员分配内存
m_name = (char*)malloc(100);
// 为 m_name 成员设置字符串值
if (m_name != NULL)
{
strcpy_s(m_name, sizeof(obj.m_name), obj.m_name);
}
// 为 m_age 成员设置初始值
m_age = obj.m_age;
cout << "调用拷贝构造函数" << endl;
}
~Student()
{
// 销毁 name 指向的堆内存空间
if (m_name != NULL)
{
free(m_name);
}
cout << "调用析构函数" << endl;
}
public:
int m_age;
char* m_name;
};
int main()
{
// 声明 Student 类型实例对象
// 调用无参构造函数
Student s1;
// 打印 Student s1 实例对象值
cout << "name : " << s1.m_name << " , age : " << s1.m_age << endl;
// 手动调用有参构造函数
// 直接调用构造函数会产生匿名对象, 涉及到该匿名对象的生命周期
Student s2 = Student(18, "Tom");
// 打印 Student s1 实例对象值
cout << "name : " << s2.m_name << " , age : " << s2.m_age << endl;
// 调用拷贝构造函数
Student s3 = Student(s2);
// 打印 Student s3 实例对象值
cout << "name : " << s3.m_name << " , age : " << s3.m_age << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}
执行结果 :
调用无参构造函数
name : name , age : 0
调用有参构造函数
name : Tom , age : 18
调用拷贝构造函数
name : Tom , age : 18
Press any key to continue . . .