【C++】类四大构造函数带示例

四大构造函数

#include <iostream>
using namespace std;
#define LEN 64

class Human {//类的首字母大写
public:
	//2.构造函数类型
	//②手动定义的默认构造函数√-又名默认构造函数
	//定义对象时自动调用默认构造函数中的值
	Human();//没有返回值也不能写返回值(void也不能写)

	//③自定义的带参数(重载-同名)构造函数√-又名自定义构造函数
	//=Human(string, int );
	Human(string name, int age);

	//④拷贝构造函数
	//④手动定义的拷贝构造函数(只写一个)√;合成的拷贝构造函数×-会同步传值,不是一次简单的复印
	//=Human(const Human& src);
	Human(const Human& );
	//④--拷贝构造函数的调用时刻
	//④①函数形参为对象,实参对象为其赋值(引用为别名不赋值)
	//④②函数返回值为对象,创建临时对象供返回(引用为别名不返回)
	//④③对象(包括对象数组)初始化,拷贝对象给其初始值--注意为初始化,即定义时赋值

	//⑤赋值构造函数--注意为定义后赋值
	//⑤手动定义的赋值构造函数√;合成的赋值构造函数×-会同步传值,不是一次简单的复印
	//等号运算符重载
	Human&operator = (const Human & src);

	void eat() {//若函数很简单且只用一二次可直接写;若多次调用则用内联函数inline
		cout << "我在吃饭!" << endl;
	}
	void hobby();
	void description() const;
//	Human getYounger(const Human man1, const Human man2);因为类的功能的返回值不能为类,所有不能定义为类的功能,要在外部定义一个函数

	string getName() const;
	int getAge() const;//方法写作函数,public只有方法,故public中全部为函数
	int getSalary();
	const char* getAddr();
	void setAddr(const char* newAddr);

private:
	//①合成的默认构造函数×
	int age = 18;//数据封装在内部,防止他人恶意篡改和隐私泄露(可内部选择不告知);类似库文件,可代码封装,只给头文件
	string name;//内部数据不建议初始化
	int salary;

	//string addr时strcpy不能用,因string属c++,char*和strcpy属c
	char* addr = NULL;//指针记得初始化
};

void Human::hobby() {
	cout << "我在做自己喜欢的事情!" << endl;
}

string Human::getName() const{
	return name;
}

int Human::getAge() const{
	return age;
}

int Human::getSalary() {
	return salary;
}

const char* Human::getAddr() {
	return addr;
}

void Human::setAddr(const char* newAddr) {
	if (!newAddr) return;
	strcpy_s(addr, LEN, newAddr);
}

void Human::description() const{
	cout << "年龄:" << age << "名字:" << name << "薪资:" << salary << "地址:" << addr << endl;
}
//---------②---------
Human::Human() {
	cout << "调用手动定义的默认构造函数" << endl;
	name = "默认名";//前面不要加类型,是调用数据成员而不是定义变量
	age = 1;
	salary = 11;

	addr = new char[LEN];//记得分配内存空间
	strcpy_s(addr, LEN, "China");
}

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

	addr = new char[LEN];//记得分配内存空间
	strcpy_s(addr, LEN, "China");
}

//---------④---------
Human::Human(const Human& src) {//别名为src
	cout << "调用手动定义的拷贝构造函数" << endl;
	name = src.name;
	age = src.age;
	salary = src.salary;

	addr = new char[LEN];//记得手动拷贝函数要分配内存空间
	strcpy_s(addr, LEN, src.addr);
}

//---------④---------
void showMsg(const Human &man) {
	cout << man.getName() << "的信息是:";
	man.description();
}
//const Human& getYounger(const Human &man1, const Human &man2) {//0
//const Human getYounger(const Human man1, const Human man2) {//3
//每多一个引用符号,少一次拷贝构造函数的调用
//调用数=对象数
Human getYounger(const Human &man1, const Human &man2) {
	if (man1.getAge() < man2.getAge()) {
		return man1;
	}
	return man2;
}

//---------⑤---------
Human& Human::operator = (const Human & src){
	name = src.name;
	age = src.age;
	salary = src.salary;

	//动态内存视需要释放
	//此处因下一步修改覆盖addr中的值,故释放原有内存
	delete addr;
	addr = new char[LEN];

	//拷贝字符数组,不能直接赋值
	//addr=src.addr;×-浅拷贝/位拷贝,只传递了字符数组首地址,即指向同一地址
	strcpy_s(addr, LEN, src.addr);

	return *this;//指针解引为对象,内容对应返回值为Human类对象的别名;返回自身,方便链式处理
}

int main() {
	//1.访问对象
	//①直接定义对象
	Human h1;
	h1.eat();
	//h1.age;×-private在main中不可访问

	//②指针指向对象
	Human* p;
	//p->hobby();×-使用了未初始化的局部变量,未指向地址.指针不能直接访问
	p = &h1;
	cout << "合成的默认构造函数:" <<"年龄:"<< p->getAge() << endl;//中断,提示p未被初始化;或打印出年龄是负值-因return age中的age未初始化-合成的默认构造函数:需将全部数据成员使用类内初始值才用

	//---------②---------
	cout << "手动定义的默认构造函数:" <<"姓名:"<< h1.getName() << endl;
	Human h2;
	cout << "手动定义的默认构造函数:" << "姓名:" << h2.getName() << endl;//默认名,不带参定义对象则其数据默认

	//---------③---------
	Human h3("带参名", 100);
	cout << "自定义的带参构造函数:" << "姓名:" << h3.getName() << endl;
	Human *p3 = &h3;
	cout<< "自定义的带参构造函数:" << "薪资:" << p3->getSalary() << endl;

	//---------④---------
	//Human h4; h4=h3;则为调用赋值构造函数
	Human h4 = h3; Human h5(h3);//完全相同
	//---------浅拷贝/位拷贝(指向/占用同一块内存)---------
	//=cout << h3.getAddr() << endl;//函数名=其返回值
	//=cout << h4.getAddr() << endl;
	h3.description(); h4.description();
	h3.setAddr("美国");
	//---------深拷贝(含手动拷贝函数声明和定义)---------
	h3.description();h4.description();

	//---------④①+④②---------
	const Human h41("41", 19);//函数定义时不必定义const
	const Human h42("42", 22);
	
	getYounger(h41, h42);

	cout << "-----------";
	showMsg(h41);

	//---------⑤---------
	Human h51("51", 51);
	Human h52;
	h52 = h51;
	showMsg(h52);

	//system("pause");VS中自动暂停,按任意键后退出
	return 0;
}

//对指针进行操作时永远要判断是否是空指针

静态与常量数据成员

#include <iostream>
using namespace std;
//extern int Cnt;

class Human {
public:
	Human();
	Human(int, string);
	Human(const Human&);

	int getAge();
	int getCnt();
	static int getCNT();
	void description();
private:
	int age;
	//const static int cnt=1;常静态,不能改变
	static int cnt;//静态数据成员不能类内初始化
	const string bloodType = "未知";//常量在C11可类内初始化
};

//const int Human::cnt = 1;const静态//若与初始化是不同,以类外赋值为准
//int Cnt = 0;全局
int Human::cnt = 0;//只有静态数据成员可以在类的外部定义,因为它不属于任何一个对象
//const string Human::bloodType = "未知";×
Human::Human() :bloodType("未知") {//string常量初始化方法,不能直接赋值;默认构造函数
	age = 0;
	//bloodType = "未知";×二进制“ = ”: 没有找到接受“const std::string”类型的左操作数的运算符(或没有可接受的转换)

	//Cnt++;
	cnt++;
}

Human::Human(int age, string bldType) :bloodType(bldType) {//自定义带参构造函数
	this->age = age;
	//Cnt++;
	cnt++;
}

Human::Human(const Human& src) {//
	age = src.age;
	//Cnt++;
	cnt++;
}
int Human::getAge() {
	return age;
}
int Human::getCnt() {//非静态成员函数调用必须有对象
	return cnt;
}

int Human::getCNT() {
	//this->age = 10;×static成员函数因为可以类调用,所以可以没有特定对象
	//age = 10;×非静态数据成员引用必须与特定对象相对,而static成员函数因为可以类调用,所以可以没有特定对象
	//Human q1;q1.age = 10;//只可以调用已确定对象的非静态数据成员和静态数据成员
	return cnt;//公用值,即静态数据成员
}
void Human::description() {
	cout << "年龄为:" << age << "血型为:" << bloodType << endl;
}

int main() {
	Human q1;
	Human q2(2, "A");
	Human q3 = q1;

	cout << "------静态数据成员------" << endl;
	//cout << "人数为:" << Cnt << endl;全局
	//cout << "人数为:" << Human::getCnt() << endl;×-非静态成员必须和特定对象相对
	cout << "人数为:" << q1.getCnt() << endl;//若成员函数为普通类型,则必须通过对象调用,不能通过类调用

	cout << "------静态成员函数------" << endl;
	cout << "人数为:" << q1.getCNT() << endl;
	cout << "人数为:" << Human::getCNT() << endl;
	
	cout << "------常量数据成员bloodType------" << endl;
	q1.description();
	q2.description();

	return 0;
}

附: string类可直接赋值, 为深拷贝, 复制一份, 地址不同<-> char * 类直接赋值为指向同一地址, 浅拷贝

#include <iostream>
using namespace std;
//string(c++)型可以直接赋值,且所在地址不同.相当于int型
int main() {
	string s1 = "肉肉";
	string s2 = s1;
	cout << s2 << endl;//肉肉
	cout << &s1 << endl;//&si≠&s2
	cout << &s2 << endl;
	return 0;
}

this用法: 不能指向类公有的静态数据成员

Human.h

#pragma once
#include <iostream>
using namespace std;
//extern int Cnt;
class Human {
public:
	Human();
	Human(int);
	Human(const Human&);

	int getAge();
	void description();

	Human& getYounger(Human&);
	Human* getOlder(Human*);

private:
	int age;
};

Human.cpp

#include "this_Human.h"

Human::Human(){//常量初始化方法
	age = 0;
}

//①形参同名:this->指向这个public函数调用的对象
//=Human::Human(int aAge) {age = aAge;}

Human::Human(int age){
	this->age = age;
}

Human::Human(const Human& src) {
	age = src.age;
}
int Human::getAge() {
	return age;
}

void Human::description() {
	cout << "年龄为:" << age << endl;
}

//②形参和返回值为引用:*this(只含一个参数即比较对象)-需要是public功能,不能是非class函数,因为要返回this
Human& Human::getYounger(Human& other) {
	if (this->age < other.age) return *this;
	return other;
}
//③形参和返回值为指针:this
Human* Human::getOlder(Human* other) {
	if (this->age > other->age) return this;
	return other;
}

main.cpp

#include "this_Human.h"

int main() {
	Human h1(1);
	Human h2(2);

	(h1.getYounger(h2)).description();//1,类的.:结合方向从左到右

	Human* p = &h1;
	p->getOlder(&h2)->description();//2,指针->:结合方向从左到右

	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值