目录
构造函数
简介
主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
默认情况下,c++编译器至少给一个类添加3个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
构造函数的执行顺序:基类->内嵌对象成员->派生类 析构顺序相反
分类
两种分类方式
按参数分为:有参构造和无参构造
如果用户定义有参构造函数,C++不在提供默认的无参构造函数,但是会提供默认拷贝构造函数
class Person {
public:
//无参构造函数
Person() {
cout << "无参构造函数" << endl;
}
Person(int a) {
age = a;
cout << "有参构造函数" << endl;
}
private:
int age;
};
按类型分为:普通构造和拷贝构造
如果用户定义拷贝构造函数,C++不会再提供其他构造函数
深拷贝和浅拷贝
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作(如果对于一些不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题)
#include<iostream>
using namespace std;
class Person {
public:
//无参构造函数
Person() {
cout << "无参构造函数" << endl;
}
Person(int a,int h) {
age = a;
height = new int(h);
cout << "有参构造函数" << endl;
}
Person(const Person& p) {
age = p.age;
if (p.height != nullptr) {
height = new int(*p.height);
}
}
~Person() {
cout << "析构函数" << endl;
if (height != nullptr) {
delete height;
height = nullptr;
}
}
private:
int age;
int* height;
};
int main()
{
Person p1(10,20);
Person p2 = p1;
return 0;
}
初始化列表
C++提供了初始化列表语法,用来初始化属性
初始化顺序于类中声明顺序有关,与初始化列表无关
class A {
public:
int m_a;
int m_b;
A(int a, int b) :m_b(b), m_a(a) {
//先初始化m_a在初始化m_b和初始化列表顺序无关与类中声明顺序有关
}
};
验证案例
#include<iostream>
using namespace std;
class A {
public:
int m_a;
int m_b;
A(int a, int b) :m_b(b), m_a(m_b) {
//先初始化m_a在初始化m_b和初始化列表顺序无关与类中声明顺序有关
}
};
int main()
{
A a(10, 20);
cout << a.m_a << endl;
return 0;
}
析构函数
简介
主要作用在于对象销毁前系统自动调用,执行一些清理工作
语法:~类名(){}
虚析构函数
作用:用于解决父类指针释放子类对象导致清理不干净造成内存泄漏的问题
由于多态使用时,如果子类中由属性开辟到了堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或纯虚析构
virtual ~类名(){}
virtual ~类名(){}=0;
案例:
#include<iostream>
using namespace std;
class Animal {
public :
virtual ~Animal() {
cout << "Animal虚构函数" << endl;
}
};
class Cat :public Animal {
string* m_name;
public:
Cat(string name) {
cout << "Cat构造函数" << endl;
m_name = new string(name);
}
~Cat() {
cout<<"Cat析构函数调用"<<endl;
if (m_name != nullptr) {
delete m_name;
m_name = nullptr;
}
}
};
int main()
{
Animal* a = new Cat("小猫");
delete a;
return 0;
}