构造函数与析构函数
1.构造函数
构造函数是类的一种特殊的函数:
(1)函数名与类名相同
(2)没有返回值
(3)可以有形参也可以没有
(4)可以时内联函数
(5)可以重载
(6)可以带默认参数
作用:在对象被创建时使用特殊的值构造对象,将对象初始化为一个特殊的状态。
构造函数一般不显示调用,在创建一个对象时,构造函数被自动调用。(用编译器完成)
若程序中未定义构造函数,编译器将自动生成一个默认构造函数,模拟人生构造函数的参数列表是空的。
如果程序中已经定义构造函数,默认情况下编译器就不再隐含生成默认构造器了,如果此时依然希望编译器生成默认构造器,可以使用“=default”
例如:
class object {
public:
object() = default; //编译器生成默认构造器
object(int a) { } //自定义构造器
};
1.1编写和使用构造函数
#include <iostream>
using namespace std;
class object {
public:
object() {
cout << "我是无参构造函数" << endl;
}
object(int a) {
cout << "我是有参构造函数" << a << endl;
}
};
int main()
{
object obj; //调用无参构造函数
object obj1(1); //调用有参构造函数
return 0;
}
1.2如何在构造函数中初始化成员变量
例如:
#include <iostream>
using namespace std;
class object {
public:
object() {
cout << "我是无参构造函数" << endl;
}
object(int a) :i(a) { //“:i(a)”表示将成员变量用传入的a的值来初始化,这个方法与在函数里面赋值的效果一样,但是这个方法效率更高
//i = a;//效果同 :i(a)
cout << "我是有参构造函数" << a << endl;
}
void showInfo() {
cout << i << endl;
}
private:
int i=1;
};
int main()
{
//object obj;
object obj(11);
obj.showInfo();
return 0;
}
1.3还可以将构造函数体写在类的外面,类里面只需要写函数声明就可以了。
#include <iostream>
using namespace std;
class object {
public:
object() {
cout << "我是无参构造函数" << endl;
}
object(int a);
void showInfo() {
cout << i << endl;
}
private:
int i=1;
};
object::object(int a) :i(a) {
cout << "我是有参构造函数" << a << endl;
}
int main()
{
//object obj;
object obj(11);
obj.showInfo();
return 0;
}
1.4委托构造函数
使用类的其他构造函数来执行初始化过程
例如:
class Clock {
public:
Clock(int a, int b):i(a),j(b) {
}
Clock():Clock(0,0){} //委托构造函数:使用类的其他构造函数来执行初始化过程
private:
int i, j;
};
1.5复制构造函数(或者称:拷贝构造函数)
复制构造函数是一个特殊的构造函数,其形参为本类的对象引用
作用是用一个已经存在的对象来构造另外一个新对象(两个对象的类型相同)
形式:
class 类名{
public:
类名(形参); //构造函数
类名 (const 类名 &对象名); //复制构造函数
// ...
}
类名::类(const 类名 &对象名) //复制构造函数的实现
{ 函数体 }
复制构造函数不显示调用,而是由编译器隐式地去调用
以下三种情况:
(1)定义对象
object a;
object b(a); //相当于 object b=a;
(2)动态创建对象
object a;
object* p=new object(a);
(3)函数的传值调用
void Test(object obj) { }
2.析构函数
对象被销毁的时候自动调用
(1)名称固定:类名前面加上波浪线“~” 形式:~类名 例如:~object(){ }
(2)没有返回值
(3)不能带参数
析构函数只能有一个,不允许重载 。析构函数不显示地调用而是在对象被销毁时,被编译器自动地调用。如果程序中未定义析构函数,编译器会自动地生成一个析构函数
3.继承中析构与构造的调用顺序(记录邵发的C++)
子类对象构建时,先调用父类构造函数,再调用子类构造函数
子类对象析构时,先调用子类析构函数,再调用父类构造函数
即构造和析构是一对相反的过程
#include <iostream>
using namespace std;
class parent {
public:
parent() {
cout << "我是父类无参数构造函数" << endl;
}
parent(int a) {
cout << "我是父类有参数构造函数,参数为:" << a << endl;
}
~parent() {
cout << "我是父类析构函数" << endl;
}
};
class child : public parent{ // " : public parent "表示继承类 parent
public:
child() {
cout << "我是子类无参数构造函数" << endl;
}
child(int a) {
cout << "我是子类有参数构造函数,参数为:" << a << endl;
}
~child() {
cout << "我是子类析构函数" << endl;
}
};
int main()
{
{
child ch; //创建一个对象,构造函数被调用
} //结束,对象的析构函数被调用
}
输出结果:
当父类有多个构造函数时可以显式地调用其中一个构造函数(使用初始化列表来调用),如果没有显示调用则调用默认的父类构造函数
下面例子中表示如何显式地调用父类的构造函数:
class parent {
public:
parent() {
cout << "我是父类无参数构造函数" << endl;
}
parent(int a) {
cout << "我是父类有参数构造函数,参数为:" << a << endl;
}
~parent() {
cout << "我是父类析构函数" << endl;
}
};
class child : public parent{
public:
child() : parent(1){ //parent(1)表示显示地调用父类带参数的构造函数“parent(int a)”
cout << "我是子类无参数构造函数" << endl;
}
child(int a) {
cout << "我是子类有参数构造函数,参数为:" << a << endl;
}
~child() {
cout << "我是子类析构函数" << endl;
}
};