类的基础性总结

虽然接触cpp也有一段时间了,今天在进行复习回顾的时候,在一些细节上还是有点欠缺,特此整理。

一、默认构造函数

1.如果在定义类的时候没有指定默认构造函数,系统就会自动生成一个构造函数,函数体为空,表示对数据成员不做任何操作;
2.如果定义了构造函数,则系统不会自动生成一个构造函数;
3.参数全部默认的构造函数只能有一个,换句话说,可以不提供参数而调用的构造函数只能有一个;

//下面两种是不能同时出现的
test(double x=1,double y=1,double z=1);
test();
//构造函数可以重载,但是具有默认参数与没有默认参数的相同形式的构造函数是不同的。但是,每一个个对象调用的构造函数必须唯一;
Tri(double x,double y=5,double z=5); //A
Tri(double x,double y,double z);	//B
Tri();								//C
/*
*Tri Tria;			//正确,调用C
*Tri Tria(4);		//正确,调用A
*Tri Tria(4,5,6);	//错误,A行与B行均满足调用条件,出现歧义;
*/

二、析构函数

1.析构函数也是一个特殊的成员函数,他的作用与构造函数相反,是在撤销对象占用的内存之前完成的一些清理工作,使得这部分内存可以被程序重新分配。且,一个类中只能有一个析构函数
2.析构函数的调用顺序正好与构造函数相反,先构造的对象后析构,后构造的对象先析构
3.一般的类可以不需要定义析构函数,即采用默认析构函数即可,但是,如果在构造函数中使用了new运算符为对象的成员数据动态分配了存储空间,则一定要在类中显示的地定义析构函数,在撤销对象时将new分配的空间用delete释放。

三、构造对象的顺序

1.与变量的作用域一样“{<一般生命周期在一对大括号内有效>}”,对象的作用域也有全局和局部之分,其中局部对象又分为静态局部对象与动态局部对象>
1).全局对象在main函数执行之前被构造。
2).静态局部对象在进入其作用域时被构造,且只能构造一次,在程序结束后才被析构
3).动态局部对象在进入其作用域时被构造,在作用域结束后被析构

所以,在日常学习与实验中,要注意每个参数的声明周期,同时需要理解的是,自己定义的类与int、double等是一样的,具有相似的性质,可以将自定义类看作是“int”或者“double”等;

class tri
{
	<do something>;
};
Tri *p=new Tri;	//动态的开辟内存

调用顺序实验

#include<iostream>
#include<string>
using namespace std;
class STR
{
	char* p;
public:
	STR(char* s);
	~STR();
};

STR::STR(char* s)
{
	p = new char[strlen(s) + 1];
	strcpy(p, s);
	cout << "调用" << p << "的构造函数" << endl;
}

STR::~STR()
{
	if (p)
	{
		cout << "调用" << p << "的析构函数" << endl;
		delete[]p;
	}
}
STR s1("全局对象");
void fun()
{
	static STR s2("局部静态对象");
	STR s3("局部动态对象");
}
int main()
{
	cout << "main begin ..." << endl;
	fun();
	fun();
	cout << "mian end ..." << endl;
	return 0;
}

在这里插入图片描述

四、 const 成员与对象

4.1 const 成员数据

1.用const声明的成员数据,称为常成员数据,其值** 必须使用参数初始化列表的构造函数进行初始化**并且这个值在程序运行过程中不能被改变。

4.2 const成员函数

如果要求成员函数中所有成员数据的值都不允许改变,则可以将这个成员函数定义为const成员函数,称为常成员函数;
常成员函数不能调用另一个非const成员函数.

//类名::类型名 函数名(参数表) const
class Tri
{
private:
	double a,b,c;
public:
	Tri(double x,double y,double z);
	double Peri() const
	{return a+b+c;}		//函数内不能改变成员函数a,b,c的值;
};

4.3 const 对象

如果要求类的对象在程序运行过程中一直保持初始值,可以将这个对象定义为常对象。

类名 const 对象名(<实参1,实参2...>)
或
const 类名 对象名(<实参1,实参2...>//推荐使用第一种,第一种直接加在对象名之前表示该对象是常对象,第二种是容易产生歧义;

1.常对象除了由系统自动调用构造函数和析构函数外,只能调用他所在类的常成员函数,而不能调用普通成员函数
2.如果一定要修改常对象中,某个数据成员的值,可以将该数据成员声明为mutable,即可变的数据成员.,然后可以在成员函数中进行修改;

#include<iostream>
#include<cmath>
using namespace std;
class Tri
{
private:
	double a,b;
	mutable double c; 		//声明c为可变的数据成员;
public:
	Tri(double x,double y,double z);
	double Peri() const; 	//常成员函数
	double Area();
	...
};
int main()
{
	Tri const tria(3,4,5);	//创建三角形常对象tria
	Tri trib(5,5,5);		//普通对象
	...
}

五、静态成员

如果将类中的某一成员数据的存储类型指定为静态类型时,这个成员数据就为各对象所共有,在内存中只占一份空间,他的值对所有的对象都是一样的,所有对象都可以引用他,相当于类中的“公共数据”;

#include<iostream>
using namespce std;
class Tri
{
	private:double a,b,c;
	static int n;		//公有静态成员数据;
	...
	
};
int Tri::n;				//静态数据成员必须要在类外进行初始化,默认值是0; 
...

说明:

1)在类中,静态成员数据的空间是公共的、唯一的,属于所有同类对象。
2)静态成员数据必须要在类体外进行初始化说明,初始化的格式为:

数据类型 类名::静态成员数据=初值;<默认值为0>

3)静态成员数据受类的访问权限限制。例如,可以将静态成员数据类型声明为private,此时,在类外不能访问该成员;
4 )静态成员数据属于类,被对象共享,定义了类以后,即使还没有创建对象,类的静态成员数据已经存在,并且可以被访问。

六、友元函数友元类

6.1友元函数

6.1.1普通函数声明为类的友元函数

有时类外函数需要访问类的私有成员数据,可以将该函数声明为友元函数:

class <className>
{
	...
	friend 函数类型 函数名 (<参数列表>;	//在类体中声明类的友元函数
	...
};

友元函数是类外函数,不是相应类的成员函数,没有类体中的this指针,需要用对象名.成员名的形式访问类中的成员数据,同时,其形参一般是对象的引用形式。

6.1.2其他类的成员函数声明为类的友元函数

class A
{
	...
	friend 函数类型B::函数名 (<参数列表>;	//在类体中声明类的友元函数
	...
};

6.2 友元类

声明一个友元类之后,友元类可以自由的引用这个类的所有成员;
例如:类B 是类A的友元类,则需要在类A中声明类B,并且一般先定义类A,在定义类B,同时对类B要作提前声明

class A
{
	...
	friend class B;
	...
}
#include<iostream>
using namespace std;
...
class B;	//首先声明类B
class A		//定义类A
{
	...
};

class B 	//定义类B
{
	...;
}

注意:
1)友元的关系是单向的而不是双向的,类A是类B的友元,不等于类B是类A的友元;
2) 友元的关系不能传递

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值