C++_对象特性

对象特性

构造函数的调用方式

#include<iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		cout << "无参构造函数调用" << endl;
	}
	Person(int age)
	{
		m_Age = age;
		cout << "有参构造函数调用" << endl;
	}
	Person(string name, int age)
	{
		m_Age = age;
		m_Name = name;
		cout << "有参构造函数调用" << endl;
	}
	Person(const Person &p)
	{
		m_Age = p.m_Age;
		cout << "拷贝构造函数调用" << endl;
	}
	~Person()
	{
		cout << "析构函数调用" << endl;
	}
private:
	string m_Name;
	int m_Age;
};

void test10()
{
	//栈上实例化调用
	//1.括号法
	Person p1;
	Person p2(10);
	Person p3("张三",20);
	Person p4(p2);
	//2.显式法
	Person p5 = Person(10);	//Person(10)是匿名对象,当前行结束,马上析构。
	Person p6 = Person{ "张三", 18 };
	Person p7 = Person(p5);
	//3.隐式法
	Person p8 = 10;	//Person p6=Person(10)
	Person p9 = p8;
	Person p10 = { "张三", 18 };
}

void test11()
{
	//堆上实例化调用
	//1.括号法
	Person *ptr1 = new Person;
	Person *ptr2 = new Person();
	Person *ptr3 = new Person(10);
}
int main()
{
	test10();
	//test11();

	system("pause");
	return 0;
}

深拷贝和浅拷贝

C++利用构造函数、拷贝构造函数和析构函数进行初始化和清理的操作,是必须有的实现。默认情况下,编译器会给一个类提供
1)默认构造函数(无参、空实现)
2)默认析构函数(无参、空实现)
3)默认拷贝构造函数(值拷贝、浅拷贝)
4)赋值运算符operator=(对属性进行值拷贝、浅拷贝)

如果有属性开辟在堆区,也需要程序员使用delete调用析构函数手动释放内存。但当使用默认拷贝构造函数、默认赋值运算符时,会带来内存重复释放(浅拷贝)的问题。一定要重写析构函数(释放堆区内存) 、拷贝构造函数(防止浅拷贝)、赋值运算符重载(防止浅拷贝)、构造函数(如果自己写了拷贝构造函数,编译器不会自动调用默认构造函数)。
如果有属性开辟到堆区,在使用多态时,要使用虚析构 函数或纯虚析构函数。

#include<iostream>
using namespace std;


class Person
{
public:
	Person(int age, int height)
	{
		m_Age = age;
		m_Height = new int(height);
		cout << "构造函数调用" << endl;
	}

	Person(const Person &p)
	{
		m_Age = p.m_Age;
		m_Height = new int(*p.m_Height);
		cout << "拷贝构造函数调用" << endl;
	}

	~Person()
	{
		if (m_Height != NULL)
		{
			delete m_Height;
			m_Height = NULL;
		}
		cout << "析构函数调用" << endl;
	}

public:
	int m_Age;
	int *m_Height;
};

void test21()
{
	Person p1(18, 160);
	Person p2(p1);
	cout << "p1年龄:" << p1.m_Age << ", p1身高:" << *p1.m_Height << endl;
	cout << "p2年龄:" << p2.m_Age << ", p2身高:" << *p2.m_Height << endl;
}


int main()
{
	test21();

	system("pause");
	return 0;
}

类对象作为类成员

1)在使用A类对象作为B类成员时,A的类中需要默认构造函数。以初始化列表的方式创建构造函数B类时,A类不需要默认构造函数。因此,当我们创建一个构造函数时,最好也添加一个默认构造函数,防止编译报错。

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


class Phone
{
public:
	/*Phone()
	{
		cout << "Phone无参构造函数调用" << endl;
	}*/
	Phone(string phoneName)
	{
		m_PhoneName = phoneName;
		cout << "Phone有参构造函数调用" << endl;
	}
	~Phone()
	{
		cout << "Phone析构函数调用" << endl;
	}
public:
	string m_PhoneName;
};

class Person
{
public:
	//Phone m_Phone=phoneName;
	Person(string personName, string phoneName):m_PersonName(personName),m_Phone(phoneName)
	{
		/*m_PersonName = personName;
		m_Phone=phoneName;*/
		cout << "Person构造函数调用" << endl;
	}
	~Person()
	{
		cout << "Person析构函数调用" << endl;
	}
public:
	string m_PersonName;
	Phone m_Phone;
};


void test31()
{
	Person p("张三", "华为");
	cout << p.m_PersonName << "拿着" << p.m_Phone.m_PhoneName << endl;

}
int main ()
{
	test31();


	system("pause");
	return 0;
}

代码分析
1)初始化列表的方式创建构造函数B类时,A类不需要默认构造函数。执行流程:
在这里插入图片描述
2)非初始化列表的方式创建构造函数B类时,A类需要默认构造函数。执行流程:
在这里插入图片描述

对象模型

1)在C++中,类内的成员变量和成员函数分开存储。非静态成员变量属于类的对象;静态成员变量和静态成员函数,所有对象共享(可以通过对象或者类名访问),存储在全局区;非静态成员函数,也只有一份函数实例,通过this指针区分哪个对象调用。

2)常对象和常函数不可以修改属性的值。非静态成员函数隐含一个this指针,this指针的本质是指针常量(指针的指向不可以更改,指向的值可以更改),用以区分调用的对象。非静态成员函数用const修饰变成常函数,使得this指针指向的值也不可以更改。常对象只能调用常函数。

#include<iostream>
using namespace std;

class Person
{
public:
	void getAB1()
	{
		cout << m_A << "," << m_B << endl;
	}
	void getAB2() const
	{
		cout << m_B << endl;
	}
	//非静态成员函数
	void func1(int a, int b)
	{
		this->m_A = a;
		this->m_B = b;
		cout << "func1调用" << endl;
	}
	//常函数
	void func2(int a, int b) const
	{
		//this->m_A = a; 常函数不可修改对象属性的值。
		this->m_B = b;
		cout << "func1调用" << endl;
	}
	//静态成员函数
	static void func3()
	{
		//m_A = 0;静态成员函数只能访问静态成员变量。
		m_C = 0;
		cout << "func2调用" << endl;
	}
private:
	//非静态成员变量
	int m_A;
	mutable int m_B;
	//静态成员变量
	static int m_C;
};

int Person::m_C = 100;

void test41()
{
	Person p1;
	p1.func1(10, 10);
	p1.getAB1();
	//静态成员属于所有对象共享,可以通过对象或者类名访问。
	Person::func3();
	p1.getAB1();
}
void test42()
{
	const Person p1;
	//p1.func1(10, 10);
	p1.func2(20, 20);
	p1.getAB2();
}

int main()
{
	//test41();
	test42();

	system("pause");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值