2020.11.12 第4节 特殊成员

2020.11.12 第4节 特殊成员

一、const成员


const 成员      
	const:不能修改  常属性
	1.const 数据成员     //常数据成员
		1.1 只能采用初始化参数列表的方式进行初始化
			构造函数名(参数1,参数2,...):数据成员1(参数1),数据成员2(参数2)...{}
		1.2 构造函数必须要初始化常数据成员
			在学常量的时候,常量必须初始化 常量的基本规则
	2.const 成员函数		//常成员函数
		2.1 注意写法
			const放在函数后面
		2.2 注意限定
			不能修改数据
		2.3 常成员函数可以和普通函数共存
	3.const 对象			//常对象
		常对象只能调用常成员函数
		普通对象优先调用普通函数
            
#include <iostream>
#include <string>
using namespace std;
class MM
{
public:
	MM(string name):num(0)
	{
		this->name = name;
	}
	//初始化参数列表 --->很重要  继承 类的组合
	MM(string name, int age) :name(name), age(age), num(0)
	{

	}
	MM(string name, int age, int num) :num(num)
	{
		this->name = name;
		this->age = age;
	}
	void print()
	{
		cout << name<<":" << age << endl;
	}
	//常成员函数
	void print() const
	{
		int i =0 ; i++;
		cout << "常函数" << endl;
		//可以使用数据成员,但是不能修改
		cout << name << ":" << age <<":"<<num<< endl;
	}
protected:
	//数据成员
	string name;
	int age;
	const int num;		//常数据成员 必须使用初始化参数列表
};
class boy
{
public:
	boy(const char* str) :str(str)
	{

	}
	boy() :str("Iloveyou")
	{

	}
	const char* str;
};
int main()
{
	//常对象:只能调用常成员函数
	const MM mm("Love");
	mm.print();			//常对象只能调用常成员函数
	MM myMM("小仙女", 18);
	myMM.print();
	return 0;
}

二、静态成员

static 修饰						 静态成员属于类 ,不属于对象 调用不需要对象
	1.static数据成员					  
		1.1 注意初始化
			1.1.1 类外初始化 但还是本类  重点
				NO.1 需要前缀
				NO.2 依旧受权限限定词限定
		1.2 注意调用
			1.2.1 它的使用可以不需要对象
			1.2.2 依旧受权限和类名限定词限定
	2.static成员函数
		2.1 static 修饰的函数			可以访问保护属性 普通函数不行
    			类内 类外 都可实现 类外需要类的限定 不需要static
		2.2 调用与访问问题
			2.2.1 调用也不需要对象 
			2.2.1 依旧受权限和类名限定词限定
#include <iostream>
#include <string>
using namespace  std;
class MM
{
public:
	//初始化参数列表的方式比较多
	MM(string name) :name(name)
	{
		count++;
	}	
	void print()
	{
		cout << count << endl;	//普通函数正常使用静态数据成员
	}
	static void printInfo();	//类中实现正常
	static void printData(MM oject);	//静态函数访问非静态成员时,一定要通过对象去指定
protected:
	string name;
public:
	static int count;
};
//类外初始化,要用类名限定,不再需要static
int MM::count = 0;					//静态数据成员 全局
//类外实现,,要用类名限定,不需要static
void MM::printInfo()
{
	//静态函数访问静态数据成员没有任何问题
	cout << count << endl;		
}
void MM::printData(MM object)
{
	//静态成员函数访问非静态数据成员,通过指定对象,传参
	//count << name << endl;
	cout << object.name << endl;
	cout << count << endl;

}
//void printData2(MM object)
//{
//	cout << object.name << endl;		//普通函数无法访问保护权限数据成员
//}
int main()
{
	//int MM::count = 0;			//静态数据成员 全局
	cout << MM::count << endl;		//依旧受权限和类名限定词限定 0
	MM mm1("yykk");
	MM mm2("oracle");
	MM mm3("LBW");
	cout << MM::count << endl;		//保留上次运行的结果	3
	mm1.print();					//3
	//静态函数的调用不需要对象
	MM::printInfo();				//3
	MM::printData(mm3);				//LBW 3 普通数据成员访问 指定对象
	return 0;
}

三、友元函数


1.友元函数:friend关键字修饰的函数就是友元函数
	1.1 类外实现不需要friend修饰
	1.2 有元函数不属于类,类外实现不需要加类名限定
	1.3 在当前函数中赋予对象具有打破类的权限限定 !! 对象
				//有元函数外创建的对象 赋予对象打破类的权限限定的权力 传参
		no.1传参的对象/对象指针
		no.2在函数体创建对象
		打破类的封装和隐藏性
	 以另一个类的成员成员函数为友元函数  了解
    	//特殊的实现,A中的函数是B的有元函数 实现放在B的下面
2.友元类
    
#include <iostream>
#include <string>
using namespace std;
class MM
{
	//友元函数不属于类 不受类的限定 可以在类的任何地方声明 类中类外都可以实现
	friend void makeBoyFriend();
	friend void makeBoyFriend(MM object);
public:
	MM(string name, int age, int money) :name(name), age(age), money(money) {};
	string name;
protected:
	void print()
	{
		cout << name << ":" << age << ":" << money << endl;
	}
	int age;
private:
	int money;
};
//不需要friend,不需要类名限定 实现访问   参数不一样可以重载 计算机要知道哪条路
void makeBoyFriend()
{
	//在当前函数中赋予对象具有打破类的权限限定
	//1.传参的对象/对象指针
	//2.在函数体创建对象
	MM boy("yykk", 18, 100);
	boy.print();
	cout << boy.name << ":<<" << boy.age << ":" << boy.age << endl;
	//打破类的隐藏和封装性
}
void makeBoyFriend(MM object)
{
	object.print();
}
/*
声明以另一个类的成员函数为友元函数
	1.用类名限定
	2.要声明一下 :告诉Boy...
	3.实现顺序问题
	   特殊的实现,A中的函数是B的有元函数 A中函数的实现放在B的下面 
*/
class Girl;
class Boy
{
public:
	void makeGirlFriend(Girl girl)   //此函数
	{
		cout << girl.name << ":" << girl.age << endl;		//智能提醒问题
	}
protected:
};
class Girl
{
	friend void Boy::makeGirlFriend(Girl girl);
public:
	Girl(string name, int gae) :name(name), age(age) {}
	string name;
protected:
	int age;
};

//特殊的实现,A中的函数是B的有元函数 实现放在B的下面   
void Boy::makeGirlFriend(Girl girl)   //此函数
{
	cout << girl.name << ":" << girl.age << endl;		//智能提醒问题
}


int main()
{
	MM mm("yykk", 18, 100);
	//mm.print();					    友元函数外的对象受类的权限限定
	//cout << mm.name << ":<<" << mm.age << ":" << mm.age << endl;
	makeBoyFriend(mm);		//有元函数外创建的对象 赋予对象打破类的权限限定的权力 传参
	//运算符重载		赋予运算符一个新的功能 
	Girl girl("Oracle", 19);
	Boy boy;
	boy.makeGirlFriend(girl);
	return 0;
}

四、友元类


友元类:
	把另一个当作一个类的友元 ,另一个类的对象就可以随意访问
互为友元类:
	注意写法 声明问题

#include <iostream>
#include <string>
using namespace std;
//友元类
class Girl
{
	friend class Boy;		//Boy类就是Girl类的友元类
public:
	Girl(string name,int age):name(name),age(age){}
	void print()
	{
		//girl不是bot的友元类
	}
	string name;
protected:
	int age;
};
class Boy
{ 
public:
	//1.
	void print()
	{
		Girl girl("Oracle", 18);
		//在当前类的任何地方girl对象都可以访问girl任何属性
		cout << girl.name << ":" << girl.age << endl;
	}
	//2.
	void print(Girl object)
	{
		cout << object.name << ":" << object.age << endl;
	}
	//3.

protected:
};
//互为友元
class A
{
	friend class B;
public:
	A(int a):a(a){}
	void print(B object);			//B类在A类后面实现

protected:
	int a;
};
class B
{
	friend class A;
public:
	B(int b) :b(b) {}
	void print()
	{
		A object(1);
		cout << object.a << endl;
	}
protected:
	int b;
};
void A::print(B object)			//B类在A类后面实现 只能提醒
{
	cout << object.b << endl;
}
int main()
{
	Boy boy;
	boy.print();

	A a(1);
	B b(2);
	a.print(b);
	b.print();
	return 0;
}

五、类的组合


类的组合:
	以另一个类的对象为数据成员
	1.构造函数写法
		1.1 必须初始化参数列表方式调用组合类的构造函数
		1.2 组合类必定会调用其他类的构造函数
			(// // MM(int ) 缺省)
	2. 构造和析构顺序问题
    
#include <iostream>
using namespace std;
class Clothes
{
public:
	Clothes(int color=0):color(color)
	{
		cout << "A" << endl;
	}
protected:
	int color;
};
class Cosmetics
{
public:
	Cosmetics(int money=0):money(money)
	{
		cout << "B" << endl;
	}
protected:
	int money;
};
class MM
{
public:									//对象名 函数参数个数  调用构造函数的过程
	MM(string name,int color,int money):cloth(color),cosmetic(money)
	{
		this->name = name;
		cout << "C1" << endl;
	}
	MM(string name):name(name)		//缺省的写法 不缺省的写法
	{
		cout << "C2" << endl;
	}
protected:
	string name;
	//构造顺序和这个声明顺序有关,和初始化参数列表无关
	//Clothes 在前面 他的构造函数先调用 然后Cosetics  最后MM自身的
	Clothes cloth;		//类名 对象名
	Cosmetics cosmetic;
};
int main()
{
	MM mm("LBW",1,100);	// A B C  析构C B A

	return 0;
}

六、类中成员函数指针


类的成员函数的函数指针
	区别:声明的时候
    1.类的限定
    2.成员函数取地址
#include <iostream>
using namespace std;
class MM
{
public:
	MM(string name,int age):name(name),age(age){}
	void print()
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
int main()
{
	/*
	error C3867: “MM::print”: 非标准语法;请使用 "&" 来创建指向成员的指针
	1. "&" 来创建指向成员的指针		&MM::print
		类名的限定写法
	错误写法 void MM::(*p)();		
	错误写法 void (*MM::p)();
	*/
	MM mm("Bug", 10);	
	void (MM:: * p)() = &MM::print;		//区分普通的函数指针
	(mm.*p)();		//调用的时候写法上注意点
	return 0;
}#include <iostream>
using namespace std;
class  MM 
{
public:
	MM(string  name, int age) :name(name), age(age) {}
	void print() 
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
int main() 
{
	MM mm("Bug", 10);
	//error C3867: “MM::print”: 非标准语法;请使用 "&" 来创建指向成员的指针
	//1. "&" 来创建指向成员的指针		&MM::print
	//错误写法 void MM::(*p)()
	//错误写法 void (*MM::p)();
	void (MM:: * p)() = &MM::print;
	(mm.*p)();		//调用的时候写法上注意点
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值