栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++:《构造析构拷贝与const、string以及this指针》

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++:《构造析构拷贝与const、string以及this指针》

目录

一、this指针

二、构造系列

1.对象的种类

2.构造函数

3.析构函数

4.实现一个date类 (万年历)练习

5.拷贝构造

6.浅拷贝与深拷贝问题

三、static与const

1.static成员

2.const


一、this指针

空类的对象占一个字节
类中的成员变量  创建对象时才存在  每个对象都有自己独立的一份
类中的成员函数  编译期存在  只有一份
this指针  关键字  指向当前调用本成员函数的对象
this指针只能在成员函数(非静态)中使用

#include 
using namespace std;


class AA
{
public:
	int a;
	char b;
public:
	void Show(int a)
	{
		cout << "AA" << endl;
		cout << this->a << " " << this->b << endl;
		this->a = a;
		//this++;
	}
};

class BB
{
public:
	void Show()
	{
		cout << "BB" << endl;
	}
};
int main()
{
	AA a;
	cout << sizeof(a) << endl;
	cout << sizeof(BB) << endl;
	system("pause");
	return 0;
}

输出:

8
1
请按任意键继续. . .



二、构造系列

1.对象的种类

#include 
using namespace std;

class AA
{
public:
	AA()
	{
		cout << "AA" << endl;
	}
	~AA()
	{
		cout << "~AA" << endl;
	}
};
//AA a; //全局大括号之后回收
int main()
{
	//AA a; //局部对象 栈区  return之后 大括号之前
	
	
	//堆区对象

	//临时对象
	cout << "---------" << endl;
	AA();
	cout << "---------" << endl;
	system("pause");
	return 0;
}

输出:

---------
AA
~AA
---------
请按任意键继续. . .

 

2.构造函数

构造函数 ,是一种特殊的方法。. 主要用来在创建对象时初始化对象, 即为对象 成员变量 赋初始值,总与new 运算符 一起使用在创建对象的语句中。. 特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的 重载 。

#include 
using namespace std;


class Student
{
public:
	const char* m_Name;
	int m_Age;
public:
	Student()
	{
		m_Name = "小明";
		m_Age = 18;
	}
	Student(const char* str)
	{
		m_Name = str;
		m_Age = 17;
	}
	Student(const char* str, int age)
	{
		m_Name = str;
		m_Age = 18;
	}
};
int main()
{
	Student stu;
	cout << stu.m_Name << " " << stu.m_Age << endl;
	Student stu1("小强");
	cout << stu1.m_Name << " " << stu1.m_Age << endl;
	Student* pStu = new Student("小芳",18);
	cout << pStu->m_Name << " " << pStu->m_Age << endl;
	Student* pStu1 = (Student*)malloc(sizeof(Student));


	system("pause");
	return 0;
}

输出:

小明 18
小强 17
小芳 18
请按任意键继续. . .





3.析构函数

析构函数与构造函数相反,当对象结束其 生命周期 ,如对象所在的 函数 已 调用 完毕时,系统自动执行析构函数。. 析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放 内存 )。

#include 
using namespace std;
#include 

class Phone
{
public:
	string m_PhoneName;
public:
	Phone(string name)
	{
		m_PhoneName = name;
		cout << "Phone的构造" << endl;
	}
	~Phone()
	{
		cout << "Phone的析构" << endl;
	}
};
class Person
{
public:
	string m_name;
	Phone m_Phone;
public:
	Person(string name,string pName):m_name(name),m_Phone(pName)
	{
		cout << "Person的构造" << endl;
	}
	~Person()
	{
		cout << "Person的析构" << endl;
	}
public:
	void Print();
};
void Person::Print()
{
	cout << m_name << "使用" << m_Phone.m_PhoneName << "的手机" << endl;
}
void test()
{
	Person p("小明", "苹果MAX");
	p.Print();
}
int main()
{
	test();



	system("pause");
	return 0;
}

输出:

Phone的构造
Person的构造
小明使用苹果MAX的手机
Person的析构
Phone的析构
请按任意键继续. . .

4.实现一个date类 (万年历)练习


//三个私有的成员变量  年  月  日
//默认出厂日期为1900-1-1
//显示当前日期
//设置日期(校验日期合法性)
//附加一个初始化函数

#include 
using namespace std;

class Date
{
private:
	int m_Year;
	int m_Month;
	int m_Day;
public:
	Date();
	Date(int year, int month, int day);
public:
	void SetYear(int year);
	void SetMonth(int month);
	void SetDay(int day);
	void Show();
	void InitDate(int year, int month, int day);
};
Date::Date()
{
	m_Year = 1900;
	m_Month = 1;
	m_Day = 1;
}
void Date::SetYear(int year)
{
	m_Year = year;
}
void Date::SetMonth(int month)
{
	if (month >= 1 && month <= 12)
	{
		m_Month = month;
	}
	else
	{
		cout << "月份违法" << endl;
	}
}
void Date::SetDay(int day)
{
	if (day >= 1 && day <= 30)
	{
		m_Day = day;
	}
	else
	{
		cout << "日期违法" << endl;
	}
}
void Date::Show()
{
	cout << m_Year << "-" << m_Month << "-" << m_Day << endl;
}
Date::Date(int year, int month, int day) :m_Year(year), m_Month(month), m_Day(day)
{

}
void Date::InitDate(int year, int month, int day)
{
	m_Year = year;
	m_Month = month;
	m_Day = day;
}
int main()
{
	Date d;
	d.Show();
	d.SetYear(2022);
	d.SetMonth(6);
	d.SetDay(13);
	d.Show();
	Date d1(2022, 6, 13);
	d1.Show();
	Date dd[5];
	for (int i = 0; i < 5; i++)
	{
		dd[i].InitDate(2022, 6, 13);
	}
	for (int i = 0; i < 5; i++)
	{
		dd[i].Show();
	}
	system("pause");
	return 0;
}

输出:

1900-1-1
2022-6-13
2022-6-13
2022-6-13
2022-6-13
2022-6-13
2022-6-13
2022-6-13
请按任意键继续. . .

5.拷贝构造

拷贝构造函数的参数可以是 const 引用,也可以是非 const 引用。 一般使用前者,这样既能以常量对象(初始化后值不能改变的对象)作为参数,也能以非常量对象作为参数去初始化其他对象。一个类中写两个拷贝构造函数,一个的参数是 const 引用,另一个的参数是非 const 引用,也是可以的。

如果类的设计者不写拷贝构造函数,编译器就会自动生成拷贝构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认拷贝构造函数”。

注意,默认构造函数(即无参构造函数)不一定存在,但是拷贝构造函数总是会存在。

不能在类中定义本类的对象
类中含有一个默认的拷贝构造函数  只有一个参数是本类类型的引用的构造函数
什么情况下会调用拷贝构造
1.用一个对象初始化另一个对象时
2.类对象作为函数参数时
3.函数返回值为类对象时     原因:用局部对象初始化临时对象

 

#include 
using namespace std;


class Student
{
public:
	const char* m_Name;
	int m_Age;
public:
	Student()
	{

	}
	Student(const char* name,int age)
	{
		m_Name = name;
		m_Age = age;
	}
	Student(Student& a)
	{
		m_Name = a.m_Name;
		m_Age = a.m_Age;
		cout << "COPY" << endl;
	}
public:
	void Show()
	{
		cout << m_Name << " " << m_Age << endl;
	}
};
void Show(Student& stu)
{
	cout << stu.m_Name << " " << stu.m_Age << endl;
}
//Student Fun()

int main()
{
	Student stu1("小明",17);
	stu1.Show();
//
	Student stu2 = stu1;
	stu2.Show();

	Student stu3(stu1);
	stu3.Show();

	Student stu4;
	stu4 = stu1;
	stu4.Show();
//
	//Show(stu1);
	//Fun();
	system("pause");
	return 0;
}

输出:

小明 17
COPY
小明 17
COPY
小明 17
小明 17
请按任意键继续. . .



6.浅拷贝与深拷贝问题

浅拷贝   将源对象的值拷贝到目标对象
深拷贝   拷贝的时候先开辟一个与源对象成员空间大小一样的空间  然后再将空间中的内容赋值过来

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。所以在delete时浅拷贝容易造成二次释放的问题,所以我们拷贝构造函数一定要深拷贝。

代码如下:

#include 
using namespace std;
//浅拷贝   将源对象的值拷贝到目标对象
//深拷贝   拷贝的时候先开辟一个与源对象成员空间大小一样的空间  然后再将空间中的内容赋值过来

class AA
{
public:
	int* p;
public:
	AA()
	{
		p = new int;
		*p = 100;
	}
	~AA()
	{
		delete p;
	}
public:
	AA(AA &a)
	{
		p = new int;
		*p = *a.p;
	}
};
void Show(AA& a)  //用类的引用作为函数参数
{
	cout << *a.p << endl;
}
int main()
{
	AA a;
	cout <<* a.p << endl;
	AA b = a;
	cout <<* b.p << endl;
	Show(a);
	system("pause");
	return 0;
}

输出:

100
100
100
请按任意键继续. . .

三、static与const

1.static成员

全局变量  使用范围整个程序  在其他文件中使用要外部引用 extern
静态变量  适用范围  在作用域定义 本作用域内   在作用域外定义 当前文件

静态成员变量  只有一份  所有对象共享 
静态成员在类外初始化
初始化格式: 类型 + 类名::+ 变量名
静态成员变量必须要在类外初始化  如果不赋值默认初始化为0
可以不用对象直接访问  类名::+变量名
依旧遵循访问修饰符的约束
普通成员函数可以使用静态成员变量
静态成员函数只能使用静态成员变量  不能使用普通成员变量
静态成员函数没有this指针
 

#include 
using namespace std;


class AA
{
public:
	static int a;
	int b;
public:
	void Show()
	{
		cout << a << " " << b << endl;
	}
	static void ShowShow();
};
int AA::a ;
void AA::ShowShow()
{
	cout << a << " " << endl;
}



int  main()
{
	cout << AA::a << endl;
	//AA a;
	a.a = 100;
	//a.b = 200;
	//a.Show();
	//AA b;
	//b.a = 1000;
	//b.b = 20;
	//b.Show();

	
	//cout << sizeof(AA) << endl;
	system("pause");
	return 0;
}

2.const

类中包含const成员变量  要在初始化列表中初始化

在类成员函数的后面加一个const 表示该函数为常函数
const放在函数返回值前 表示函数返回值是一个常量
常函数限制了this指针  不能通过this指针去修改当前对象中的成员变量
常对象只能调用常函数

#include 
using namespace std;


class AA
{
public:
	const int a;
	int b;
public:
	AA() :a(100)
	{
		b = 200;
	}
public:
	void Show()
	{
		cout << a << endl;
		this->b = 300;
		cout << b << endl;
	}
	
	void ShowShow() const;
};
void AA::ShowShow() const
{
	cout << a << endl;
	//this->b = 300;
	cout << b << endl;
}
int main()
{
	AA a;
	a.Show();
	a.ShowShow();

	const AA b;
	b.ShowShow();
	system("pause");
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1012266.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号