4种构造函数

构造函数的作用

在创建一个新的对象时,自动调用的函数,用来进行“初始化”工作:对这个对象内部的数据成员进行初始化。

构造函数的特点

  1. 自动调用(在创建新对象时,自动调用)
  2. 构造函数的函数名,和类名相同
  3. 构造函数没有返回类型
  4. 可以有多个构造函数(即函数重载形式)

构造函数的种类

1.默认构造函数

没有参数的构造函数,称为默认构造函数。

(1)合成的默认构造函数

#include <iostream>
using namespace std;

class Human {
public:
	string getName();
	int getAge();
	int getSalary();

private:
	string name;
	int age = 18;  //类内初始值
	int salary;

};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

int main() {
	Human h1;// 创建时使用合成的默认初始化构造函数
	cout << "年龄: " << h1.getAge() << endl;     //使用了类内初始值
	cout << "薪资:" << h1.getSalary() << endl;  //没有类内初始值

	return 0;
}

代码执行结果:

一般情况下,都应该定义自己的构造函数,不要使用“合成的默认构造函数”。

仅当数据成员全部使用了“类内初始值”,才宜使用“合成的默认构造函数”。

只要手动定义了任何一个构造函数,编译器就不会生成“合成的默认构造函数。

(2)手动定义的默认构造函数

常称为“默认构造函数”。

#include <iostream>
using namespace std;

class Human {
public:
	Human();//手动定义的“默认构造函数”
	string getName();
	int getAge();
	int getSalary();

private:
	string name;
	int age;
	int salary;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

Human::Human() {//初始化
	name = "佚名";
	age = 18;
	salary = 20000;
}

int main() {
	Human h1;// 创建时使用自定义的默认初始化构造函数
	cout << "姓名: " << h1.getName() << endl;
	cout << "年龄: " << h1.getAge() << endl;
	cout << "薪资:" << h1.getSalary() << endl;

	return 0;
}

代码执行结果:

说明:如果某数据成员使用类内初始值,同时又在构造函数中进行了初始化,那么以构造函数中的初始化为准。相当于构造函数中的初始化,会覆盖对应的类内初始值。

2.自定义的构造函数

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);//自定义的构造函数(带参数)
	string getName();
	int getAge();
	int getSalary();

private:
	string name;
	int age;
	int salary;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

Human::Human(string name, int age, int salary) {
	cout << "调用自定义的构造函数" << endl;
	this->name = name;//this是一个特殊的指针,指向这个对象本身
	this->age = age;
	this->salary = salary;
	

}

int main() {
	Human h1("Andy", 26, 30000);
	cout << "姓名: " << h1.getName() << endl;
	cout << "年龄: " << h1.getAge() << endl;
	cout << "薪资:" << h1.getSalary() << endl;

	return 0;
}

代码执行结果:

 会覆盖类内初始值。

3.拷贝构造函数

(1)手动定义的拷贝构造函数

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	Human(const Human &other);//other可省略,引用类型
	string getName();
	int getAge();
	int getSalary();
	void description();//测试使用

private:
	string name;
	int age;
	int salary;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << endl;
}
Human::Human(string name, int age, int salary) {
	cout << "调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	

}
Human::Human(const Human& other) {//相当于const Human &other = h1;
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;
}

int main() {
	Human h1("Andy", 26, 30000);
	cout << "h1  ";
	h1.description();
	Human h2 = h1;//调用拷贝构造函数
	cout << "h2  ";
	h2.description();
	Human h3(h1);//第二种写法
	cout << "h3  ";
	h3.description();
	
	return 0;
}

代码执行结果:

(2)合成的拷贝构造函数 

当然,不使用自定义拷贝函数,则会调用默认的拷贝函数。

在一般情况下也不会出现问题:

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	string getName();
	int getAge();
	int getSalary();
	void description();

private:
	string name;
	int age;
	int salary;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << endl;
}
Human::Human(string name, int age, int salary) {
	cout << "调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	

}

int main() {
	Human h1("Andy", 26, 30000);
	cout << "h1  ";
	h1.description();
	Human h2 = h1;//调用拷贝构造函数
	cout << "h2  ";
	h2.description();
	Human h3(h1);//第二种写法
	cout << "h3  ";
	h3.description();
	
	return 0;
}

代码执行结果:

 但在使用合成拷贝函数时存在缺点:使用“浅拷贝”,特别是在私有数据为指针的时候。

 “浅拷贝”示例:

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	string getName();
	int getAge();
	int getSalary();
	void description();
	void setAddr(const char* addr);

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

void Human::setAddr(const char* newAddr) {
	if (!addr) {
		return;
	}
	strcpy_s(this->addr, 16, newAddr);
}

Human::Human(string name, int age, int salary) {
	cout << " 调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

int main() {
	Human h1("Andy", 26, 30000);

	cout << " h1  ";
	h1.description();
	Human h2 = h1;
	cout << " h2  ";
	h2.description();
	Human h3(h1);
	cout << " h3  ";
	h3.description();

	h1.setAddr("America");
	cout << endl;
	cout << " ----------modified h1----------" << endl;
	cout << " h1  ";
	h1.description();
	cout << " h2  ";
	h2.description();
	cout << " h3  ";
	h3.description();

	return 0;
}

代码执行结果:

在函数中只修改了h1的地址,结果h2,h3的地址也随着改变了。这种现象是由于“浅拷贝”导致。

解决方案:在自定义的拷贝构造函数中,使用”深拷贝“。

”深拷贝“示例:

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	Human(const Human &other);
	string getName();
	int getAge();
	int getSalary();
	void description();
	void setAddr(const char* addr);

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

void Human::setAddr(const char* newAddr) {
	if (!addr) {
		return;
	}
	strcpy_s(this->addr, 16, newAddr);
}

Human::Human(string name, int age, int salary) {
	cout << " 调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human::Human(const Human& other) {
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;

	addr = new char[16];//"深拷贝"
	strcpy_s(addr, 16, other.addr);
}

int main() {
	Human h1("Andy", 26, 30000);

	cout << " h1  ";
	h1.description();
	Human h2 = h1;
	cout << " h2  ";
	h2.description();
	Human h3(h1);
	cout << " h3  ";
	h3.description();

	h1.setAddr("America");
	cout << endl;
	cout << " ----------modified h1----------" << endl;
	cout << " h1  ";
	h1.description();
	cout << " h2  ";
	h2.description();
	cout << " h3  ";
	h3.description();

	return 0;
}

代码执行结果:

(3)调用拷贝构造函数的场合

1.调用函数时,实参是对象,形参不是引用类型。

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	Human(const Human &other);
	string getName();
	int getAge();
	int getSalary();
	void description();

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

Human::Human(string name, int age, int salary) {
	cout << "调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human::Human(const Human& other) {
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;

	addr = new char[16];
	strcpy_s(addr, 16, other.addr);
}

void showMsg(Human man) {//值传递Human man = h1;
	cout << man.getName() << "的基本信息:";
	man.description();
}

int main() {
	Human h1("Andy", 26, 30000);
	showMsg(h1);

	return 0;
}

代码执行结果:

 如果函数的形参是引用类型,就不会调用拷贝构造函数。

如果将

void showMsg(Human man) {//值传递Human man = h1;
	cout << man.getName() << "的基本信息:";
	man.description();
}

改为:

void showMsg(Human &man) {//h1的别名;
	cout << man.getName() << "的基本信息:";
	man.description();
}

就不会调用拷贝函数,代码执行结果如下:

如果当心引用不安全,可以使用const:

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	Human(const Human &other);
	string getName() const;//const表示不能修改内部成员
	int getAge();
	int getSalary();
	void description() const;

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() const {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() const {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}


Human::Human(string name, int age, int salary) {
	cout << "调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human::Human(const Human& other) {
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;

	addr = new char[16];
	strcpy_s(addr, 16, other.addr);
}

void showMsg(const Human &man) {
	cout << man.getName() << "的基本信息:";
	man.description();
}

int main() {
	Human h1("Andy", 26, 30000);
	showMsg(h1);

	return 0;
}

2.函数的返回类型是类,而且不是引用类型。

#include <iostream>
using namespace std;

class Human {
public:
	Human(string name, int age, int salary);
	Human(const Human &other);
	string getName();
	int getAge();
	int getSalary();
	void description();

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

Human::Human(string name, int age, int salary) {
	cout << "调用自定义构造函数" << endl;
	this->name = name;
	this->age = age;
	this->salary = salary;
	
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human::Human(const Human& other) {
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;

	addr = new char[16];
	strcpy_s(addr, 16, other.addr);
}

Human getBetterMan(Human man1, Human man2) {
	if (man1.getSalary() > man2.getSalary()) {
		return man1;
	}
	else {
		return man2;
	}
}

int main() {
	Human h1("Andy", 26, 30000);
	Human h2("Van", 22, 15000);
	getBetterMan(h1, h2);//返回临时对象

	return 0;
}

代码执行结果:

同样加上引用就不会调用拷贝函数:

Human &getBetterMan(Human &man1, Human &man2) {
	if (man1.getSalary() > man2.getSalary()) {
		return man1;
	}
	else {
		return man2;
	}
}

代码执行结果:

3.对象数组的初始化列表中,使用对象。

#include <iostream>
using namespace std;

class Human {
public:
	Human();
	Human(const Human &other);
	string getName();
	int getAge();
	int getSalary();
	void description();


private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

Human::Human() {
	name = name;
	age = age;
	salary = salary;
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human::Human(const Human& other) {
	cout << "调用拷贝构造函数" << endl;
	name = other.name;
	age = other.age;
	salary = other.salary;

	addr = new char[16];
	strcpy_s(addr, 16, other.addr);
}



int main() {
	Human f1, f2, f3, f4;
	Human F4[4] = { f1, f2, f3, f4 };

	return 0;
}

代码执行结果:

 4.赋值构造函数

如果没有定义赋值构造函数,编译器会自动定义“合成的赋值构造函数”,与其他合成的构造函数,是“浅拷贝”(又称为“位拷贝”)。

“浅拷贝”:

#include <iostream>
using namespace std;

class Human {
public:
	Human();
	string getName();
	int getAge();
	int getSalary();
	void description();
	void setAddr(const char* addr);

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

void Human::setAddr(const char* newAddr) {
	if (!addr) {
		return;
	}
	strcpy_s(this->addr, 16, newAddr);
}

Human::Human() {
	name = "cc";
	age = 18;
	salary = 1000;
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}


int main() {
	Human f1, f2;
	f2 = f1;//自动调用默认赋值构造函数
	f1.description();
	f2.description();

	cout << "-------modified h1-------" << endl;
	f1.setAddr("新加坡");
	f1.description();
	f2.description();
	
	return 0;
}

代码执行结果:

#include <iostream>
using namespace std;

class Human {
public:
	Human();
	Human& operator=(const Human& other);//=运算符重载
	string getName();
	int getAge();
	int getSalary();
	void description();
	void setAddr(const char* addr);

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}

void Human::description() {
	cout << "name: " << name << " age: " << age << " salary:" << salary << " address: " << addr << endl;
}

void Human::setAddr(const char* newAddr) {
	if (!addr) {
		return;
	}
	strcpy_s(this->addr, 16, newAddr);
}

Human::Human() {
	name = "cc";
	age = 18;
	salary = 1000;
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}

Human& Human::operator=(const Human& other) {
	if (this == &other) {//f1=f1的情况
		return *this;
	}
	cout << "调用赋值构造函数" << endl;
	//f1 = f2;就会自动调用f1.operator=(f2);
	name = other.name;
	age = other.age;
	salary = other.salary;
	//如果有必要,需要先释放自己的内存
	//delete addr;
	addr = new char[16];
	strcpy_s(addr, 16, other.addr);
	// 返回该对象本身的引用, 以便做链式连续处理,比如 a = b = c;
	return *this;
}

int main() {
	Human f1, f2;
	f2 = f1;//自动调用赋值构造函数
	f1.description();
	f2.description();

	cout << "-------modified h1-------" << endl;
	f1.setAddr("新加坡");
	f1.description();
	f2.description();
	
	return 0;
}

代码执行结果:

5.析构函数

作用:对象销毁前,做清理工作。具体的清理工作,一般和构造函数对应。比如:如果在构造函数中,使用new分配了内存,就需在析构函数中用delete释放。

如果构造函数中没有申请资源(主要是内存资源),那么很少使用析构函数。

没有返回值,没有参数,最多只能有一个析构函数。

使用方法:不能主动调用。对象销毁时,自动调用。如果不定义,编译器会自动生成一个析构函数(什么也不做)

#include <iostream>
using namespace std;

class Human {
public:
	Human();
	string getName();
	int getAge();
	int getSalary();
	//析构函数
	~Human();

private:
	string name;
	int age;
	int salary;
	char *addr;
};

string Human::getName() {
	return name;
}
int Human::getAge() {
	return age;
}
int Human::getSalary() {
	return salary;
}


Human::Human() {
	cout << "调用构造函数: " << this << endl;
	name = "cc";
	age = 18;
	salary = 1000;
	addr = new char[16];
	strcpy_s(addr, 16, "China");
}


Human::~Human() {
	cout << "调用析构函数: "<< this << endl;
	delete addr;
}

void test() {
	Human h1;
	{
		Human h2;
	}
	cout << "test() end" << endl;
}

int main() {
	test();

	return 0;
}

代码执行结果:

 

  • 34
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

run sun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值