c++基础

5.12

1、构造函数与析构函数

#include<iostream>
using namespace std;
//构造函数和析构函数默认必须有
class Person
{
public:
	//构造函数
	//1、无返回值无void
	//2、函数名与类名相同
	//3、可以有参数,可以发生重载
	//4、函数调用类对象之前先调用构造函数只调一次
	Person()
	{
		cout << "构造函数" << endl;
	}
	//析构函数
	//1、无无
	//2、函数名与类名相同,前加~
	//3、无参数,不重载
	//4、函数释放类对象前先析构
	~Person()
	{
		cout << "析构函数" << endl;
	}
};
void test1()
{
	Person p;
}
int main()
{
	test1();//局部变量p函数执行完立即析构
	Person p;//全局变量,执行完并不立即析构
	system("pause");
	return 0;
}

成员私有化设置中的构造与析构函数调用

#include<iostream>
using namespace std;
class Person
{
public:
	Person()
	{
		cout << "构造" << endl;
	}
	~Person()
	{
		cout << "析构" << endl;
	}
	void setx(int x)
	{
		m_x = x;
	}
	int getx()
	{
		return m_x;
	}
private:
	int m_x;
};
void test1()
{
	Person p1;
	p1.setx(20);
	cout<<p1.getx()<<endl;
}
int main()
{
	Person p;
	p.setx(10);
	cout << p.getx() << endl;
	test1();
	system("pause");
	return 0;
}

构造函数的分类与调用

#include<iostream>
using namespace std;

class Person
{
public:
	//无参构造
	Person()
	{
		cout << "无参构造" << endl;
	}
	//有参构造
	Person(int a)
	{
		cout << "有参构造" << endl;
		m_age = a;
	}
	//拷贝构造
	Person(const Person& p)
	{
		cout << "拷贝构造" << endl;
		m_age = p.m_age;
	}
	~Person()
	{
		cout << "析构" << endl;
	}
	int m_age;
};

//调用
void test1()
{
	//括号法
	Person p1;
	Person p2(10);
	Person p3(p2);
	cout << p2.m_age << endl;
	cout << p3.m_age << endl;
	//注意事项
	//无参构造括号法不加括号
	//Person p1(); 编译器将之认作函数声明处理
}
void test2()
{
	//显示法
	//Person p1;
	//Person p2 = Person(10);
	//Person p3 = Person(p2);
	//cout << p2.m_age << endl;
	//cout << p3.m_age << endl;
	//显示法中的匿名操作应用
	//Person(10);匿名有参构造创建对象创建完毕后立即释放
	//Person(p3);匿名拷贝构造函数创建对象,编译器将括号自动忽略,Person p3;重定义操作
}
void test3()
{
	//隐式转换法
	Person p1;
	Person p2 = 10;
	Person p3 = p2;
	cout << p2.m_age << endl;
	cout << p3.m_age << endl;
}
int main()
{
	test2();
	system("pause");
	return 0;
}

拷贝构造函数的调用时机

//拷贝构造函数的调用时机
#include<iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		cout << "无参构造" << endl;
	}
	Person(const Person& p)
	{
		cout << "拷贝构造" << endl;
		m_age = p.m_age;
	}
	int m_age;
};
//调用时机
void test1(Person& p)
{
	Person p1 = p;
}
Person test2()
{
	Person p1;
	cout << (int)&p1 << endl;
	return p1;//拷贝构造
	//拷贝构造将函数的值返回时,先拷贝一份返回,原函数值直接释放
}
int main()
{
	//1、复制对象
	//Person p1;//无参构造
	//Person p2(p1);//拷贝构造
	//2、值传递
	//test1(p1);//拷贝构造值传递将p1复制一份传入函数
	//3、返回
	Person p3 = test2();//无参构造
	cout << (int)&p3 << endl;
	system("pause");
	return 0;
}

//构造函数的调用规则
//创建一个类,编译器默认三个构造函数,无参构造、有参构造、拷贝构造
//人为创建一个有参构造,则编译器仅保留拷贝构造
//人为创建一个拷贝构造,则编译器默认构造函数均不保留

2、深浅拷贝

浅拷贝的问题所在,简单的拷贝黏贴,如果在堆区开辟一块内存,则浅拷贝后两个指针指向同一个区域,释放的时候会出现某一个重复释放的非法操作,释放按照栈区先进后出的原则 

解决方法,利用深拷贝,创建两个堆区内存

#include<iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		cout << "无参构造" << endl;
	}
	Person(int age,int height)
	{
		m_height=new int(height);
		cout << "有参构造" << endl;
		m_age = age;
	}
	Person(const Person& p)
	{
		cout << "拷贝构造" << endl;
		m_age = p.m_age;
		//m_height = p.m_height;默认浅拷贝操作,将p的指针拷贝一份,两个指针指向相同的堆区内存
		//深刻拷贝操作,堆区开辟内存,存放p的指针解引用的数据
		m_height = new int(*p.m_height);
	}
	~Person()
	{	
		if (m_height != NULL)
		{
			delete m_height;
			m_height = NULL;
		}
		cout << "析构" << endl;
	}
	int m_age;
	int* m_height;
};

void test1()
{
	Person p1(10,180);
	cout << "p1年龄:"<< p1.m_age  << "身高:" << *p1.m_height << endl;
	Person p2(p1);
	cout << "p2年龄:"<< p2.m_age  << "身高:" << *p2.m_height << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

3、类对象作为类成员

//类对象作为类成员
#include <iostream>
using namespace std;

class Phone
{
public:
	Phone()
	{
		cout << "Phone默认构造" << endl;
	}
	//Phone(string pname)
	//{
	//	m_pname = pname;
	//	cout << "Phone有参构造" << endl;
	//}
	~Phone()
	{
		cout << "Phone析构函数" << endl;
	}
	string m_pname;
};
class Person
{
public:
	//Person(string name,string pname): m_name(name),m_p(pname)//初始化列表问题,基本格式
	//{
	//	cout << "Person构造函数" << endl;
	//}
	
	//类对象作为类成员时,当不使用初始化列表的格式,要对Phone有个默认构造函数,
	Person(string name, string pname) 
	{
		cout << "Person构造函数" << endl;
		m_name = name;
		m_p.m_pname = pname;
	}

	~Person()
	{
		cout << "Person析构函数" << endl;
	}
	string m_name;
	Phone m_p;
};

void test1()
{
	Person person("张三", "apple");
	cout << person.m_name << "拿着" << person.m_p.m_pname << "手机" << endl;
}
但其它类对象作为本类成员时,先构造其他类对象再构造本类对象
析构的顺序与构造相反
int main()
{
	test1();
	system("pause");
	return 0;
}

4、静态成员变量

#include<iostream>
using namespace std;

class Person
{
	//静态成员
//1、所有对象共享
//2、类内声明类外初始化
//3、有权限
//4、两种访问方式,类名访问和类对象访问
public:
	static int m_age;
private:
	static int m_height;
};
int Person::m_age = 10;
int Person::m_height = 180;

void test1()
{
	Person p1;
	cout << "p1年龄:" << p1.m_age << endl;
	Person p2;
	p2.m_age = 20;//在一个对象内将静态变量更改
	cout << "p1年龄:" << p1.m_age << endl;//另一个对象里跟着更改,对象共享
}

void test2()
{
	Person p1;
	cout << "p1年龄:" << p1.m_age << endl;//类对象访问
	cout << "p1年龄:" << Person::m_age << endl;//类名访问
}

int main()
{
	//test1();
	//test2();
	system("pause");
	return 0;
}

静态成员函数


#include<iostream>
using namespace std;

class Person
{
	//静态成员函数
public:
	static void func()
	{
		//静态成员函数只能访问静态成员变量
		//id = 3;
		m_age = 30;
		cout << "this is func " <<m_age << endl;
	}	
	static int m_age;
	int id;
	//静态成员函数的属性设置
private:
	static void func2()
	{
		cout << "this is func2" << endl;
	}

};
int Person::m_age = 0;//类外初始化
void test3()
{
	Person p1;
	p1.func();//类对象访问静态成员函数
	Person::func();//类名访问静态成员函数
}
int main()
{
	test3();
	system("pause");
	return 0;
}

这一块有个点不太清晰了,静态成员函数只能够访问静态成员变量,因为非静态成员变量不具有对象共享性

成员变量与成员函数分开存储

//成员函数和成员变量分开存储
#include<iostream>
using namespace std;

class Person
{
public:
	static int m_age;//静态成员变量不属于类的对象
	int m_age2;//非静态成员变量属于类的对象上,占4字节
	static void func() {}//静态成员函数不属于类的对象
	void func2() {}//非静态成员函数不属于类的对象上
};

void test1()
{
	Person p1;//单个对象的字节大小为1
	cout << sizeof(p1) << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

5、this指针

指针指向调用成员函数的对象,this指向对象,则*this可解析出该对象,返回*this即返回对象

//this指针
#include<iostream>
using namespace std;
//this指针指向调用成员函数的对象,既然如此,返回对象本身可直接进行return *this

class Person
{
public:
	Person(int age)
	{
		m_age = age;
	}
	Person& PersonAddAge(Person& p)
	{
		this->m_age += p.m_age;
		return *this;//返回p1本体,采用引用接收
		//如果采用值返回的方式,则拷贝构造一个新的变量,用新变量进行调用增加函数
	}
	int m_age;
};

void test1()
{
	Person p1(18);
	cout << "p1年龄:" << p1.m_age << endl;
	Person p2(20);
	//要求连续调用年龄增加函数,则使该函数返回一个p1即可,this指向p1,*this即可为p1
	p1.PersonAddAge(p2).PersonAddAge(p2).PersonAddAge(p2);
	cout << "p1年龄:" << p1.m_age << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

空指针不可访问成员变量

//空指针不可访问成员变量
#include<iostream>
using namespace std;

class Person
{
public:
	void showage()
	{
		if (this == NULL)
		{
			return; //保证代码的健壮性
		}
		//this指针默认存在,指向对象表示该对象的年龄,但是该对象为空
		cout << this->m_age << endl;
	}
	int m_age = 10;
};

void test1()
{
	Person* p = NULL;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

常函数与常对象

//常函数与常变量
#include<iostream>
using namespace std;
class Person
{
public:
	//每个成员函数内部都有一个默认的this指针,指向调用该函数的对象,且指向一定不可改变
	//但是指针指向的值可以改变,如果加上一个const则限制值也不可以改变
	//如果设置一个可变变量,可无视const
	void show() const
	{
		//m_age = 100;
		m_height = 188;
	}
	int m_age;
	mutable int m_height;
};

//常对象
void test1()
{
	const Person p;//const限制为常对象
	//p.m_age = 10;常对象不可更改非可变变量的值
	p.m_height = 186;
	p.show();//常对象只能调用常函数,因为普通函数内部可以修改变量,调用相当于侧面修改变量的值
}
int main()
{

	system("pause");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值