【C++学习】类和对象--对象特性(1)

构造函数和析构函数

对象的初始化和清理是两个非常重要的安全问题

        一个对象或变量没有初始状态,对其使用后果是未知的

        使用完一个对象或变量,没有及时清理,也会造成一定的安全问题

 C++利用构造函数和析构函数解决上述问题,这两个函数会被编译器自动调用,完成对象的初始化和清理操作。

对象的初始化和清理是编译器强制要我们做的事情,因此如果我们不提供构造和析构函数,编译器会提供(编译器提供的构造和析构函数是空实现

语法

构造函数语法: 类名(){}

1.没有返回值,也不写void

2.函数名称与类名相同

3.构造函数可以有参数,因此可以发生重载

4.程序在调用对象时候会自动调用构造,无需手动调用,而且只会调用一次 

析构函数:~类名(){}

1.没有返回值,也不写void

2.函数名称与类名相同,在名称前加上符号~

3.构造函数不可以有参数,因此不可以发生重载

4.程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次 

(感觉这部分内容了解一下就行

C++ 类构造函数 & 析构函数 | 菜鸟教程 (runoob.com)

C++ 拷贝构造函数 | 菜鸟教程 (runoob.com)

构造函数的分类及调用 

按照是否传入参数分类,分为无参构造(默认构造)和有参构造

按照类型               分类,分为普通构造                     和拷贝构造

 拷贝调用时机

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

void test01()
{
    person  p1(20);
    person  p2(p1);
}

2.值传递的方式给函数参数传值

void dowork(person p)
{

}
void test02()
{
    person  p;//默认构造
    dowork(p);//拷贝构造
}

3.值方式返回局部对象

person dowork2()
{
    person p1;//默认构造
    return p1;//拷贝构造
}
void test03()
{
    person p=dowork2();
}

构造函数调用规则

1.创建一个类,C++编译器会给每个类都添加至少3个函数

默认构造  (空实现

析构函数  (空实现

拷贝构造  (值拷贝

 2.如果我们写了有参构造函数,编译器就不再提供默认构造,但会提供拷贝构造函数。

    如果我们写了拷贝构造函数,编译器就不再提供其他的普通构造函数。

(级别:拷贝>有参>默认)

深拷贝与浅拷贝

浅拷贝:编译器提供的都是浅拷贝。简单的赋值也是浅拷贝

深拷贝:在堆区重新申请空间,进行拷贝操作

malloc  /   new    的东西在堆区,堆区的数据要手动开辟,手动释放

浅拷贝带来的问题

用new把数据创建在堆区,并用指针去接收

int *m_height;
m_height=new int (height);
~person()//析构函数,将堆区元素释放
{
		if (m_height != NULL)
		{
			delete m_hight;
			m_hight = NULL;
		}
}

这里会出现bug!!

【C++学习】类和对象--对象特性(1)_第1张图片

浅拷贝带来了问题:堆区操作被重复释放 

 利用深拷贝解决

重新在堆区申请内存,也就是让P1指向一块堆区,P2也指向一块堆区。

自己实现一个拷贝构造函数,解决浅拷贝带来的问题

person(const person &p)
{
		//m_height = p.m_height;   编译器默认构造函数
		m_height=new int(*p.m_height);
}

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

初始化列表

C++提供了初始化列表语法,用来初始化属性。

语法:构造函数():属性1(值1),属性2(值2)…{}

传统初始化操作

person(int a, int b, int c)
	{
		m_A = a;
		m_B = b;
		m_C = c;
	}

初始化列表初始化属性

person() :m_A(10), m_B(20), m_C(30)
	{

	}
person(int a,int b,int c) :m_A(a), m_B(b), m_C(c)
	{

	}

类对象作为类的成员

C++类中的成员可以是另一个类的对象,我们称该对象为对象成员。

class A{};
class B
{
	A a;
	
};
#include
#include
using namespace std;

class phone
{
public:
	phone(string pname)
	{
		m_pname = pname;
	}
	string m_pname;

};
class person
{
public:
	person(string name, string pname):m_name(name),m_phone(pname){}
	string m_name;
	phone m_phone;
	
};
int main()
{
	person p("张三", "apple");

	system("pause");
	return 0;
}

这种情况下会先构造phone类,才会构造person类

当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构的顺序与构造的顺序相反。

先构造phone,先析构person

你可能感兴趣的:(c++学习,学习,c++)