2021-8-2 C++进阶学习 -> 4.2类和对象--对象的初始化和清理

目录

4.2.1 构造函数和析构函数

4.2.3拷贝构造函数调用时机

4.2.4构造函数调用规则

4.2.5深拷贝与浅拷贝

4.2.6初始化列表

4.2.7类对象作为类成员

4.2.8静态成员以及函数

4.2.1 构造函数和析构函数

构造函数
    没有返回值,不用写void
    函数名 与类名相同
    构造函数可以有参数,可以发生重载
    创建对象的时候,构造函数会自动调用,而且只调用一次

析构函数 进行清理的操作
    没有返回值 不写void
    函数名和类名相同 在名称前面加~
    析构函数不可以有参数 不可以发生重载
    对象在销毁前 会自动调用析构函数 而且只会调用一次

#include <iostream>
#include <string>
using namespace std;

class person {
public:
	//构造函数
	//没有返回值,不用写void
	//函数名 与类名相同
	//构造函数可以有参数,可以发生重载
	//创建对象的时候,构造函数会自动调用,而且只调用一次
	person() {
		cout << "person构造函数的调用" << endl;
	}

	//2、析构函数 进行清理的操作
	//没有返回值 不写void
	//函数名和类名相同 在名称前面加~
	//析构函数不可以有参数 不可以发生重载
	//对象在销毁前 会自动调用析构函数 而且只会调用一次
	~person() {
		cout << "person的析构函数的调用" << endl;
	}
};
void perso() {
	person p;
}
int main() {
	//person i;
	perso();
	system("pause");
}

4.2.2构造函数的分类以及调用

1、构造函数的分类以及调用
分类
按照参数来分类     无参构造(默认构造)  有参构造
按照类型分类        普通构造函数                 拷贝构造函数

    1、括号法
    person p1;//默认构造函数调用
    person p2(10);//有参构造函数
    person p3(p2);//拷贝构造函数

    注意事项1
    调用默认构造函数的时候,不要加()
    因为下面这行代码,编译器认为是函数的声明,不会认为在创建对象
    person p1(); 

    void func();

    2、显示法

    person(10); //匿名对象 特点:当前行执行结束之后,系统会立即回收掉匿名对象

    注意事项2
    不要利用拷贝构造函数来 初始化匿名对象 编译器会认为person(p3) === person p3;
    编译器会认为为对象的声明

    3、隐式转化法

#include <iostream>
#include <string>
using namespace std;

//1、构造函数的分类以及调用
//分类
//   按照参数来分类     无参构造(默认构造) 有参构造
//   按照类型分类		普通构造函数		 拷贝构造函数
class person
{
public:
	//构造函数
	person() {
		cout << "person的无参构造函数的调用" << endl;
	}

	person(int a) {
		age = a;
		cout << "person的有参构造函数的调用" << endl;
	}

	//拷贝构造函数
	person(const person &p)
	{
		//将传入的人身上的所有属性,拷贝到我身上
		age = p.age;
		cout << "person的拷贝构造函数的调用" << endl;
	}
	~person()
	{
		cout << "person的析构函数的调用" << endl;
	}

	int age;
};

void text01()
{
	//1、括号法
	//person p1;//默认构造函数调用
	//person p2(10);//有参构造函数
	//person p3(p2);//拷贝构造函数

	//注意事项1
	//调用默认构造函数的时候,不要加()
	//因为下面这行代码,编译器认为是函数的声明,不会认为在创建对象
	//person p1();

	//void func();
	//cout << "p2的年龄为:"<< p2.age << endl;
	//cout << "p3的年龄为:" << p3.age << endl;

	//2、显示法
	person p1;
	person p2 = person(10);//有参构造
	person p3 = person(p2);//拷贝构造

	//person(10); //匿名对象 特点:当前行执行结束之后,系统会立即回收掉匿名对象
	//cout << "aaaaa" << endl;

	//注意事项2
	//不要利用拷贝构造函数来 初始化匿名对象 编译器会认为person(p3) === person p3;
	//编译器会认为为对象的声明
	//person(p3);

	//3、隐式转化法
	person p4 = 10;// 相当于 person p4= person(10)
	person p5 = p4;
}



int main() {

	text01();
	system("pause");
}

4.2.3拷贝构造函数调用时机

拷贝构造函数调用时机

1、使用一个已经创建完毕的对象来初始化一个新对象

2、值传递二点方式给函数参数传值

3、值方式返回局部对象

#include <iostream>
#include <string>
using namespace std;
class person
{
public:
	person()
	{
		cout << "person的构造函数调用" << endl;
	}

	person(int age)
	{
		Age = age;
		cout << "person的有参函数调用" << endl;
	}

	person(const person &p)
	{
		Age = p.Age;
		cout << "person的拷贝函数调用" << endl;
	}

	~person()
	{
		cout << "person的析构函数调用" << endl;
	}
	int Age;
};

//拷贝构造函数调用时机

//1、使用一个已经创建完毕的对象来初始化一个新对象
void text01()
{
	person p1(20);
	person p2(p1);

	cout << "p2的年龄为:" << p2.Age << endl;
}

//2、值传递二点方式给函数参数传值
void dowork(person p)
{
}
void text02()
{
	person p;
	dowork(p);
}
//3、值方式返回局部对象
person dowork2()
{
	person p1;
	return p1;
}
void text03()
{
	person p = dowork2();
}
int main() {
	text01();
	text02();
	text03();
	system("pause");
}

4.2.4构造函数调用规则

构造函数的调用规则
1、创建一个类,c++编译器会给每个类都添加至少三个函数
默认函数 (空实现)
析构函数 (空实现)
拷贝构造 (值拷贝)

2、  如果我们写了有参构造,编译器不再提供默认构造,依然提供拷贝构造
        如果我们写了拷贝构造函数,编译器就不再提供其他的普通构造函数

#include <iostream>
#include <string>
using namespace std;
//构造函数的调用规则
//1、创建一个类,c++编译器会给每个类都添加至少三个函数
//默认函数 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)

//2、如果我们写了有参构造,编译器不再提供默认构造,依然提供拷贝构造
//如果我们写了拷贝构造函数,编译器就不再提供其他的普通构造函数
class person
{
public:
	person()
	{
		cout << "person的默认构造函数调用" << endl;
	}

	person(int age)
	{
		Age = age;
		cout << "person的有参构造函数调用" << endl;
	}

	person(const person &p)
	{
		Age = p.Age;
		cout << "person的拷贝构造函数调用" << endl;
	}
	~person()
	{
		cout << "person的析构函数调用" << endl;
	}
	int Age;
};

void text01()
{
	person p;
	p.Age = 18;

	person p2(p);

	cout << "p2的年龄为:" << p2.Age << endl;
}

void text02()
{
	person p(28);
	person p2(p);
}
int main() {

	text01();
	text02();
	system("pause");
}

4.2.5深拷贝与浅拷贝

深拷贝与浅拷贝
浅拷贝带来的问题:
堆区的内存重复释放 这个问题要用深拷贝来解决

总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

#include <iostream>
#include <string>
using namespace std;

//深拷贝与浅拷贝
//浅拷贝带来的问题:
//堆区的内存重复释放 这个问题要用深拷贝来解决
class person
{
public:
	person()
	{
		cout << "person的默认构造函数调用" << endl;
	}

	person(int age,int height)
	{
		Age = age;
		Height = new int(height);
		cout << "person的有参构造函数调用" << endl;
	}

	//自己实现拷贝构造函数 解决浅拷贝带来的问题
	person(const person &p)
	{
		cout << "person拷贝函数调用" << endl;
		Age = p.Age;
		//Height = p.Height;编译器默认实现这段代码

		Height = new int(*p.Height);
	}
	~person()
	{
		//将堆区开辟的数据做释放的操作
		if (Height != NULL)
		{
			delete Height;
			Height = NULL;
		}
		cout << "person的析构函数调用" << endl;
	}
	int Age;
	int *Height;
};

void text01()
{
	person p1(18,160);
	cout << "p1的年龄:" <<p1.Age<< "身高为:" << *p1.Height << endl;

	person p2(p1);
	cout << "p2的年龄:" << p2.Age <<"身高为:"<<*p2.Height<< endl;
}
int main() {

	text01();
	system("pause");
}

4.2.6初始化列表

初始化列表初始化属性
    person(int a,int b,int c) :A(a), B(b), C(c)
    {

    }

person(10,20,30);

#include <iostream>
#include <string>
using namespace std;

//初始化列表
class person
{
public:

	//person(int a, int b, int c)
	//{
	//	A = a;
	//	B = b;
	//	C = c;
	//
	//}

	//初始化列表初始化属性
	person(int a,int b,int c) :A(a), B(b), C(c)
	{

	}
	int A;
	int B;
	int C;

};

void text01()
{
	person p(10, 20, 30);
	//person p;
	cout << "A = " << p.A << endl;
	cout << "B = " << p.B << endl;
	cout << "C = " << p.C << endl;

}
int main() {

	text01();
	system("pause");
}

4.2.7类对象作为类成员

当其他类的对象作为本类的成员,构造时候先构造类对象,再构造自身,析构函数运行则相反

#include <iostream>
#include <string>
using namespace std;

//类对象作为类成员
class Phone
{
public:

	Phone(string pname)
	{
		pName = pname;
		cout << " phone的构造函数调用" << endl;
	}
	~Phone()
	{
		cout << "phone的析构函数调用" << endl;
	}
	//手机品牌名称
	string pName;
};
class person
{
public:

	person(string name, string pname):Name(name),Phone(pname)
	{
		cout << "person的构造函数调用" << endl;
	}
	~person()
	{
		cout << "person的析构函数调用" << endl;
	}
	//姓名
	string Name;
	//手机
	Phone Phone;
};
//当其他类的对象作为本类的成员,构造时候先构造类对象,再构造自身,析构
void text01()
{
	person p("张三", "苹果max");
	cout << p.Name << "拿着:" << p.Phone.pName << endl;
}

int main() {

	text01();
	system("pause");
}

4.2.8静态成员以及函数

1、静态成员

   1、所有成员都共享同一数据
    2、编译阶段就分配内存
    3、类内声明,类外初始化操作

#include <iostream>
#include <string>
using namespace std;

//静态成员变量
class person 
{
public:
	//1、所有成员都共享同一数据
	//2、编译阶段就分配内存
	//3、类内声明,类外初始化操作
	static int A;

	//静态成员变量也是有访问权限的
private:
	static int B;
};

int person::A = 100;

void text01()
{
	person p;
	cout << p.A << endl;

	person p2;
	p2.A = 200;

	cout << p.A << endl;
}

void text02()
{
	//静态成员变量 不属于某个对象上 所有兑现都共享同一份数据
	//因此静态成员变量有两种访问方式

	//1、通过对象进行访问
	person p;
	cout << p.A << endl;

	//2、通过类名进行访问
	cout << person::A << endl;

	//cout << person::B << endl; 不可访问 类外访问不到私有的静态成员
}
int main() {

	text01();
	text02();
	system("pause");
}

2.静态成员函数
所有对象共享同一个函数  
静态成员函数只能访问静态成员变量

静态成员函数   可以访问    静态成员变量

静态成员函数  不可以访问  非静态成员变量 无法区分到底是哪个对象的成员

静态成员函数也是有访问权限的,类外访问不到私有静态成员函数

访问方式有两种:1、通过对象进行访问

                             2、通过类名来进行访问

#include <iostream>
#include <string>
using namespace std;
//静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量

class person
{
public:

	//静态成员函数
	static void func()
	{
		A = 100;//静态成员函数   可以访问    静态成员变量
		//B = 100; 静态成员函数  不可以访问  非静态成员变量 无法区分到底是哪个对象的成员
		cout << "静态成员函数调用" << endl;
	}

	static int A;//静态成员变量
	int B;

	//静态成员函数也是有访问权限的

private:
	static void func2() {
		cout << "静态成员函数调用" << endl;
	}
 };

//有两种访问方式
void text01()
{
	//1、通过对象进行访问
	person p;
	p.func();
	//2、通过类名来进行访问
	person::func();
	
	//p.func2();类外访问不到私有静态成员函数

}
int main() {

	text01();
	system("pause");
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值