02-2 构造函数的分类和调用
构造函数:用于初始化对象。
构造函数的语法:类的名称() {}
- 构造函数没有返回值,但是也不能写
void
。 - 函数的名称与类的名称相同
- 构造函数可以有参数,因此可以发生重载(函数重载:相同的函数名称,不同的执行内容。可参考笔记。)
- 程序在调用对象的时候会自动调用构造,无须手动调用,而且会且仅会调用一次。
分类:
-
按照参数分:
-
有参构造(存在传入参数);
Person(int a) { cout << "这是有参构造函数" << endl; }
-
无参构造(没有传入的参数),无参构造又称之为默认构造;
Person() { cout << "这是无参构造函数" << endl; }
-
-
按照类型分:
-
普通构造;
Person(int age) { m_age = age; cout << "这是普通构造函数" << endl; }
只要不是像
const class Persion& p
的传入都是普通构造。 -
拷贝构造;
Person(const class Person& p) { m_age = p.m_age; cout << "这是拷贝构造函数" << endl; }
拷贝构造函数:拷贝一份完全一样的类出来。其中需要注意的是,要使用
const
和引用的方式传入,比如上面所示:const class Persion& p
。拷贝构造:将传入数据的所有属性都拷贝到新的对象上。
-
调用方法:
-
括号法;
class Person p1; //这是无参构造函数 class Person p2(10); //这是有参构造函数 class Person p3(p2); //这是拷贝构造函数
-
显示法;
class Person p1; //这是无参构造函数 class Person p2 = class Person(10); //这是有参构造函数 class Person p2 = class Person(p2); //这是拷贝构造函数
显示法的右侧,比如说
class Persion(10);
,单单说class Persion(10);
,我们称之为:匿名对象。匿名对象的特点:当这一行执行结束后,会立刻回收匿名对象所占用的内存空间。但是,但我们在匿名对象赋值给一个有名称的对象时,则有名称的对象就会被设置数据值。比如说
class Person p2 = class Person(10);
,先创建一个class Person(10)
的匿名对象,然后将这个匿名对象的数据值赋值给class Person p2
。执行完成这一行的命令之后,则删除匿名对象的数据并回收匿名对线所占用的内存空间。比如说这样:
class Person int main() { class Person(10); cout << "aaa" << endl; }
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
这是构造函数 这是析构函数 aaa
-
隐式转换法。
class Person p1 = 10; class Person p2 = p1;
在这里,编译器会把上面自动改为:
class Person p1 = class Persion(10); class Person p2 = class Persion(p1);
注意事项:
- 利用括号法的时候,调用默认构造函数(也就是无参构造)的时候,不要加小括号
()
。因为如果这样写class Persion p1();
,编译器会当做是一个函数的声明(函数内声明函数是被允许的),不会被认为是创建对象。 - 不要利用拷贝构造函数初始化匿名对象。比如说
class Person (p2);
。编译器会认为等价于class Person (p2) = class Person p2;
。这样就存在两个对象p2
了。编译器会认为重复定义而导致错误。
:-)