C++使用构造函数和析构函数实现对象的初始化和清理。这两个函数的函数名称与类名相同,且都会被编译器自动调用。如果我们不提供构造和析构,编译器会提供空实现。
构造函数 | 析构函数 | |
---|---|---|
语法 | 类名(){} | ~类名(){} |
返回值 | 没有返回值也不写void | 没有返回值也不写void |
参数 | 可以有参数,因此可以发生重载 | 不可以有参数,因此不可以发生重载 |
调用情形 | 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次 | 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次 |
测试代码
#include<iostream>
using namespace std;
class Person {
public:
Person() {
cout << "构造函数调用" << endl;
}
~Person() {
cout << "析构函数调用" << endl;
}
};
void test() {
Person p;
}
int main() {
test();
return 0;
}
无参构造函数示例(也叫默认构造函数)
#include<iostream>
using namespace std;
class Person {
public:
Person() {
cout << "无参构造函数调用" << endl;
}
~Person() {
cout << "析构函数调用" << endl;
}
};
void Test1() {
Person p; //调用无参构造函数不能加括号,否则会被编译器误认为是一个函数声明
}
int main() {
Test1();
return 0;
}
有参构造函数示例
#include<iostream>
using namespace std;
class Person {
public:
Person(int a) {
age = a;
cout << "有参构造函数调用" << endl;
}
~Person() {
cout << "析构函数调用" << endl;
}
public:
int age;
};
void Test2() {
Person p(18);//括号法
cout <<"p的年龄是"<< p.age << endl;
}
int main() {
Test2();
return 0;
}
拷贝构造函数示例
#include<iostream>
using namespace std;
class Person {
public:
Person(int a) {
age = a;
cout << "有参构造函数调用" << endl;
}
Person(const Person& p) {
age = p.age;
cout << "拷贝构造函数调用" << endl;
}
~Person() {
cout << "析构函数调用" << endl;
}
public:
int age;
};
void Test3(Person&p) {
cout <<"p的年龄是"<< p.age << endl;
}
int main() {
Person p1 = Person(10);
Person p2 = Person(p1);
Test3(p2);
return 0;
}
注意:构造函数没有返回值,因此也没有类型。它的作用只是对对象进行初始化,因此不需要在前面声明类型。它不需要用户调用,也不能被用户调用,可以用一个类对象初始化另一个类对象。
如:
Time t1;
Time t2=t1;
此时,把对象t1的各数据成员的值复制给t2相应各成员,而不对t2调用构造函数.
用参数初始化表对数据成员初始化
类名::构造函数名([参数表])[:成员初始化表]{[构造函数体]}
方括号内可有可无。
如:Box::Box(int h,int w,int len):height(h),width(w),length(len){}
当构造函数遇上默认参数
为了避免歧义,一般不会同时使用构造函数的重载和有默认参数的构造函数。
析构函数不能被重载,所以一个类可以有多个构造函数,但只能有一个析构函数。调用析构函数的次序正好与调用构造函数的次序相反。
【先构造的后析构,后构造的先析构】
相当于一个栈,先进后出。