关于“类”

这篇文章主要是对类的总结

前言

成员函数定义在类外,类内格式可参考类外

一、类的组成

1.类

代码如下(示例):

class CDate					//创建类 CDate
{
private:                   //省略访问属性,默认为private
	int Year;
	int Month;
	int Day;			//定义数据成员 Year,Month,Day
protected:

public:
	CDate(int x, int y, int z);    //构造函数声明		
	CDate(const CDate& date);     //复制构造函数声明
	~CDate();					 //析构函数声明
	void Display();				//成员函数 Display
};

2.构造函数

构造函数:用于初始化数据成员。系统会自动生成无参数的构造函数,并在创建对象时自动调用。如果类定义中已经为类提供了任意一种形式的构造函数,编译器就不会再提供默认的无参构造函数。

(1)构造函数的函数名=类名

(2)构造函数无返回值,不能指定返回类型,不允许添加“void”

(3)构造函数为publi属性,否则定义对象时无法自动调用构造函数

(4)构造函数只在创建对象时由系统自动调用

(5)构造函数支持重载

类外定义构造函数

//方式一
CDate::CDate(int x, int y, int z)
{
	x = Year;
	y = Month;
	z = Day;
}
//方式二
CDate::CDate(int x, int y, int z):Year(x), Month(y),Day(z){}

3.复制构造函数

复制构造函数:用一个已存在的对象初始化另一个新创建的同类对象,它是一个同类对象的常引用。

复制构造函数由系统自动调用,情况有三:

(1)明确表示由一个已定义的对象初始化一个新对象。

(2)函数的形式参数为一个对象,当发生函数调用、对象作为实参传递给函数形参时,注意,如果形式参数时引用或指针,就不会调用复制构造函数,因为此时不会产生新对象。

(3)对象作为函数返回值。

可参考文章:

https://blog.csdn.net/qq_66582995/article/details/128904536?spm=1001.2014.3001.5502

4.析构函数

析构函数:当对象生命周期结束时,需要释放所占内存资源,程序将自动调用类的析构函数。

以下对析构函数的几点说明:

(1)属于类的成员函数,函数名=~类名

(2)没有返回值类型,前面不能加“void”,必须定义为public

(3)没有形式参数,不能被重载,每个类有且仅有一个析构函数

(4)由系统自动调用执行,情况有二:①对象生命周期结束时

                                                               ②用new动态创建的对象,用delete释放申请的内存时

析构函数的调用顺序永远与构造函数的调用顺序相反

类外定义析构函数

CDate::~CDate()
{
	//内容,比如下面:
	cout << "Destructor:" << Year << "-" << Month << "-" << Day << endl;
}

5.静态成员

静态成员可以在同一个类的不同对象之间提供数据共享

即使没有创建任何类对象,静态成员也是存在的。

1.静态数据成员

初始化:静态数据成员要在创建任何对象之前就被初始化,因此,类中的静态数据成员的初始化必须在类外进行。

代码如下:

class Croster
{
public:
	static int Count;//声明静态数据成员
private:
	string name;
	int Math;
	int English;
	int Sum;
};
//静态数据成员的初始化
int Croster::Count = 100;//格式:类型 类名::静态数据会成员名=初始值;

所谓共享,就是所有对象的数据成员都是同一个,对象A如果修改了静态数据成员Count,那么在B,C中的静态数据成员Count就是修改后的,是动态的,是共享的。

例如,

#include<iostream>
#include<string>
using namespace std;
class Croster
{
public: static int Count;//声明静态数据成员
private:
	string name;
	int Math;
	int English;
	int Sum;
public:
	Croster(string na = "undef", int m = 100, int e = 100);
	void Display();
	int Cumulation();
};

//静态数据成员类外定义
int Croster::Count = 100;//初始化静态数据成员为100
//构造函数
Croster::Croster(string na, int m, int e) :name(na), Math(m), English(e)
{
	cout << "欢迎新同学" << endl;
	Sum = Math + English;
	Count--;
}
//显示函数
void Croster::Display()
{
	cout << name << endl;
	cout << "Math:" << Math << endl;
	cout << "English:" << English << endl;
	cout << "Sum:" << Sum << endl;
}
//Cumulation函数
int Croster::Cumulation()
{
	Sum = Math + English;
	return Sum;
}
//main函数
int main()
{
	cout << "Remainder=" << Croster::Count << endl;//没有创建任何类时,静态成员Count已经存在,可以直接访问
	Croster list[3];//创建了3个对象,系统自动调用构造函数,初始化数据成员,Count值减3
	cout << "Remainder=" << list[1].Count << endl;//这3个语句的Count
	cout << "Remainder=" << list[2].Count << endl;//是完全一样的,
	cout << "Remainder=" << list[3].Count << endl;//Count是共享的。
	Croster stu_A;//创建对象stu_A,Count值减1
	cout << "Remainder=" << stu_A.Count << endl;//通过对象访问Count
	cout << "Remainder=" << Croster::Count << endl;//通过直接访问数据成员访问Count
	return 0;
}

 运行结果:

2.静态成员函数

某个成员函数声明为static,该函数将独立于本类的任何实例。即使类没有创建任何对象,静态成员函数也已存在并可以被调用,在此情况下,静态成员函数只能访问静态数据成员,不允许访问非静态数据成员。

例如,

#include<iostream>
#include<string>
using namespace std;
class Croster
{
public: static int Count;//声明静态数据成员
private:
	string name;
	int Math;
	static int Sum;//新声明的私有静态数据成员
public:
	Croster(string na = "undef", int m = 100);
	static void Display();//静态成员函数
};

//静态数据成员类外定义
int Croster::Count = 100;//初始化静态数据成员为100
int Croster::Sum;//默认初始值为0
//构造函数
Croster::Croster(string na, int m) :name(na), Math(m)
{
	cout << "欢迎新同学" << endl;
	Count--;
	Sum += Math;
}
//显示函数
void Croster::Display()
{
	//cout << name << endl;
	//cout << "Math:" << Math << endl;
	//会报错,静态成员函数不允许访问非静态成员name,Math
	cout << "Sum:" << Sum << endl;
}
//main函数
int main()
{
	//cout  << Croster::Sum << endl; //私有静态成员不可访问
	Croster::Display();//无任何对象时,可用类名调用静态成员函数
	Croster list[3]={Croster("aaa",70),Croster("bbb",80) ,Croster("ccc",90) };//创建了3个对象
	list[1].Display();
	list[2].Display();//Display()中的Sum为静态成员,是每个对象所共享的,他们输出的Sum为同一个值
	Croster stu_A("ddd");//创建对象stu_A,实际是stu_A("ddd",100),类中的构造函数是带参数的
	stu_A.Display();
	return 0;
}

运行结果:

 

6.友元

能有一个该类外部的函数或者另一个类能够访问该类中私有数据成员,即是友元。

友元的3种形式:

(1)一个不属于任何类的普通函数声明为当前类的友元,此函数称为当前类的友元函数

(2)一个其他类的成员函数声明为当前类的友元,此成员函数称为当前类的友元成员

(3)另一个声明为当前类的友元,此类称为当前类的友元类

1.友元函数

由于Equal()是一个普通函数,不是友元函数,不能直接访问类的私有数据成员GPA ,所以要借助取值函数GetGPA()来提取GPA进行比较。

//部分代码
bool Equal(Croster &A, Croster &B)//定义一个普通函数
{
	if (A.GetGPA() == B.GetGPA())//A,B是类Croster的对象,GetGPA()是类Croster的成员函数
		return true;
	else
		return false;
}

当将Equal()函数声明为类Croster的友元函数,就可以直接访问类的私有成员。
友元函数的声明, 没有确切要求,访问属性是任意的,放哪都行。因为友元函数不是成员函数,它既不是公有也不是私有。

格式:friend 函数返回类型 函数名(形式参数);

class Croster
{
	friend bool Equal(Croster&, Croster&);//类内声明友元函数
private:
	double GPA;
	//......其他定义
};
//类外定义友元函数
bool Equal(Croster &A, Croster &B)
{
	if (A.GPA == B.GPA)//友元函数直接访问Croster类的私有数据成员
		return true;
	else
		return false;
}

2.友元成员

3.友元类

二、类与类间的关系

1.继承与派生

C++中,一个基类可以派生出多个派生类,一个派生类也可以由多个基类派生而成,派生类也可以作为新的基类,继续派生出新的派生类。

2.派生类的定义与访问权限

定义派生类的语法格式如下,

class 派生类名:继承方式 基类名1[  ,继承方式 基类名2,......,继承方式 基类名 n]

{

   //派生类新增的数据成员和成员函数定义

};

访问权限如下图,

公有继承方式

保护继承方式

私有继承方式

(1)基类的private成员不可以被继承

(2)基类的public和protected成员可以被继承

(3)基类的构造函数和析构函数不能被继承

特别地,可以使用using改变派生类的权限

可以参考:https://blog.csdn.net/qq_33726635/article/details/105145498

三、类模板

类模板不是一个实实在在的类,是一组类的集合。

它没有任何可执行代码,需要使用类模板时,应对其中的类型参数进行赋值,将其实例化为模板类。


类模板的定义

格式:

template<class 类型参数1,class 类型参数2,class 类型参数3,...,class 类型参数n>//class可以换为typename

class 类名

{

        ...//数据成员与成员函数的定义与实现

};


(1)template是一个声明模板的关键字。

(2)class和typename关键字指明其后是一个类型参数。

(3)类型参数是形式化的参数,在使用中可以用char,int,double,数组,类等任意数据类型进行实例化。

#pragma once
#include<iostream>
using namespace std;
template<class T1,class T2>//类模板中用到两种类型参数
//template<typename T1,typename T2>与上面语句等效
class Example 
{
public:
	Example(T1, T2);
	void print()
	{
		cout << "x=" << x << ",y=" << y << endl;
	}

protected:
	T1 x;
	T2 y;
};
//类外定义成员函数
template<class T1,class T2>//class可以换为typename
Example<T1,T2>::Example(T1 a,T2 b)
{
	x = a;
	y = b;
}
//类外定义print()函数
//template<class T1, class T2>
//void Example<T1, T2>::print()
//{
//	cout << "x=" << x << ",y=" << y << endl;
//}

类模板的使用(实例化)

#include<D:\VScode\Const\template.h>
int main()
{
	Example<int, int>a(10, 20);//实例化
	Example<int,double> b(20,20.5);//实例化
	Example<char, int>c('M', 99);//实例化
	a.print();
	b.print();
	c.print();
	return 0;
}

运行结果:


总结

还在更新中......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值