自定义构造函数 拷贝构造函数 赋值构造函数和析构函数
本篇总代码:
#include <iostream>
using namespace std;
class Human {
public:
Human();//自定义构造函数
Human(const Human &);//拷贝构造函数
Human& operator=(Human &other);//赋值构造函数
void getAge() const;
~Human();//析构函数
private:
int age=20;
char *p;
};
Human::Human() {
cout << "使用了自定义的构造函数" << endl;
p = new char[32];
}
Human::Human(const Human &other) {
cout << "使用了拷贝构造函数" << endl;
age = 18;
}
Human& Human::operator=(Human &other) {
cout << "使用了赋值构造函数" << endl;
if (this == &other) {
return *this;
}
age = 16;
}
void Human::getAge() const{
cout << age << endl;
}
Human::~Human() {
cout << "使用了析构函数" << endl;
delete[] p;
}
int main(void) {
Human human1,human2,human3=human1;
human1.getAge();
human2.getAge();
human3.getAge();
human2 = human1;
human1.getAge();
human2.getAge();
human3.getAge();
system("pause");
return 0;
}
可以直接在类内写类的方法:
class Human {
public:
void getAge(){//在类内写类的方法
cout << age << endl;
}
private:
int age=20;
char *p;
};
如何在类外写类的方法?
使用 返回类型 类名+作用域分解运算符::(双冒号)+方法名 的方式,见以下代码:
class Human {
public:
void getAge();
private:
int age=20;
char *p;
};
void Human::getAge() {//在类外写类的方法
cout << age << endl;
}
创建一个Human类:
class Human {
public:
Human();//自定义构造函数
Human(const Human &);//拷贝构造函数
Human& operator=(Human &other);//赋值构造函数
void getAge() const;
~Human();//析构函数
private:
int age=20;
char *p;
};
构造函数都是没有类型的(void int char),这些构造函数其实都有默认的版本,如果没有自定义的构造函数就会使用默认版本的构造函数,默认构造函数不对成员进行初始化,而拷贝构造函数和赋值构造函数简单地将一个对象所有成员的值复制给另一个对象.既然如此,那为什么还要自己写构造函数呢?现在暂且不讲,我们先分析一下这些自己写的构造函数.
1.自定义构造函数
Human::Human() {
cout << "使用了自定义的构造函数" << endl;
p = new char[32];
}
在创建对象的时候自动调用,用于对对象的成员进行初始化以及进行动态内存分配.在C++11标准中允许在类定义时初始化数据成员,在定义Human类的时候我们就使用了这个特性:
class Human {
public:
......
private:
int age=20;//初始化数据成员
char *p;
};
2.拷贝构造函数
Human::Human(const Human &other) {//参数必须为静态类的引用类型
cout << "使用了拷贝构造函数" << endl;
age = 18;
}
拷贝构造函数在用一个对象创建一个新的对象时自动使用,就是以下这段代码中的human3:
Human human1,human2,human3=human1;
3.赋值构造函数
Human& Human::operator=(Human &other) {//参数要为类的引用类型
cout << "使用了赋值构造函数" << endl;
if (this == &other) {
return *this;
}
age = 16;
}
在看到这个方法名的时候会不会觉得很奇怪?这个函数实际上对"="号做了重载,operator是操作符的意思,"operator="的意思就是操作等号运算符.以后要重载运算符的时候都要按照这个模板写.
赋值构造函数在将一个对象复制给另一个已经创建好的对象时自动使用:
int main(void) {
Human human1,human2,human3=human1;
human1.getAge();
human2.getAge();
human3.getAge();
human2 = human1;//这里使用了赋值构造函数
......
4.析构函数
Human::~Human() {
cout << "使用了析构函数" << endl;
delete[] p;
}
析构函数在对象销毁时自动调用,常用于释放动态内存分配.
回到上面的问题,为什么有默认版构造函数还要自己写呢?那是因为在成员是指针的时候会出大问题,系统创建的默认赋值构造函数只会执行浅拷贝,即将被拷贝对象的数据成员的值一一赋值给新创建的对象,若该类的数据成员中有指针成员,则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同.当指针指向的数据改变时,这些对象的成员所指向的值都会改变,不仅破坏了成员的私有性,而且还不安全,更严重的是delete该指针时则会导致两次重复delete而出错!
类的const成员方法
细心的同学已经发现了,在之前的代码中有一个很奇怪的点:
class Human {
public:
......
void getAge() const;
private:
......
};
......
void Human::getAge() const {
cout << age << endl;
}
在函数名后面加了一个const,这是什么意思呢?这里的const是作用于这个方法的,作用是该方法内部不能修改成员,比如以下代码会报错:
void Human::getAge() const {
age = 30;
cout << age << endl;
}
当你不希望该方法能修改成员值的时候使用.