C++ 类中会用到的关键字之-friend(virtual、override、friend、default、delete、final)

C++ 类中会用到的关键字之-friend(virtual、override、friend、default、delete、final)

接上篇文章,此篇内容主要梳理friend相关内容,如有不合理地方请大家及时联系,多谢!

3.friend(友元)

c++中引入friend,引入目的如下:

  1. 对于没有继承关系的类,如果有关联,或需要访问类内私有成员的情况下,使用友元较为方便;
  2. 友元破坏了类的封装性和隐藏性,使用时需格外小心;
友元特性注意点 说明
1 友元关系不能被继承
2 友元关系是单向的。若类B是类A的友元,类A不一定是类B的友元
3 友元关系具有非传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元
4 另:不能把其他类的私有成员函数或者其他类的虚函数声明为友元

1)友元函数

  1. 在定义一个类的时候,可以把一些函数(包括全局函数和其他类的非私有成员函数)声明为定义类的友元,这些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了
  2. 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数

友元函数例子:

#include<iostream>
#include<stdlib.h>
#include<string>

class BaseProduct;

typedef struct 
{
	int iPrice;
	int iNum;
	std::string strDescription;
}ProductAttr;

class BaseCustomer
{
public:
	BaseCustomer() {std::cout << "Here is BaseCustomer Constructor!" << std::endl;}
	virtual ~BaseCustomer() {std::cout << "Here is BaseCustomer Destructor!" << std::endl;}
	//这里只能声明,不能内联,否则导致"不完全类型的非法使用"
	void getProductAttributes(ProductAttr* struCurProAttr, BaseProduct* baseProduct);

private:
	std::string strName;
};

class BaseProduct
{
public:
	BaseProduct(){std::cout << "Here is BaseProduct Constructor!" << std::endl;}
	virtual ~BaseProduct(){std::cout << "Here is BaseProduct Destructor!" << std::endl;}
	virtual void initBaseProduct() 
	{
		iPrice = 101;
		iNum = 2;
		strDescription = "new Base product!";
	}
	//全局函数使用类对象中很多私有成员时:声明为友元
	friend void useBaseProductAllMemb(BaseProduct* baseProduct);
	//类成员函数使用其他类中很多私有成员时:声明为友元
	friend void BaseCustomer::getProductAttributes(ProductAttr* struCurProAttr, BaseProduct* baseProduct);
private:
	int iPrice ;
	int iNum;
	std::string strDescription;
};


void useBaseProductAllMemb(BaseProduct* baseProduct)
{
	std::cout << "BaseProduct iPrice:" << baseProduct->iPrice << std::endl;
	std::cout << "BaseProduct iNum:" << baseProduct->iNum << std::endl;
	std::cout << "BaseProduct strDescription:" << baseProduct->strDescription << std::endl;
}

void useBaseProductAllMemb(ProductAttr* struCurProAttr)
{
	std::cout << "ProductAttr iPrice:" << struCurProAttr->iPrice << std::endl;
	std::cout << "ProductAttr iNum:" << struCurProAttr->iNum << std::endl;
	std::cout << "ProductAttr strDescription:" << struCurProAttr->strDescription << std::endl;
}

void BaseCustomer::getProductAttributes(ProductAttr* struCurProAttr, BaseProduct* baseProduct)
{
	struCurProAttr->iNum = baseProduct->iNum;
	struCurProAttr->iPrice = baseProduct->iPrice;
	struCurProAttr->strDescription = baseProduct->strDescription;
}

int main()
{
	BaseProduct basePro;
	BaseCustomer baseCust;
	useBaseProductAllMemb(&basePro);
	
	ProductAttr struCurProAttr;
	basePro.initBaseProduct();
	baseCust.getProductAttributes(&struCurProAttr, &basePro);
	useBaseProductAllMemb(&struCurProAttr);

	return 0;
}

测试结果:

Here is BaseProduct Constructor!
Here is BaseCustomer Constructor!
BaseProduct iPrice:0
BaseProduct iNum:0
BaseProduct strDescription:
ProductAttr iPrice:101
ProductAttr iNum:2
ProductAttr strDescription:new Base product!
Here is BaseCustomer Destructor!
Here is BaseProduct Destructor!

2)友元类
一个类 BaseProduct可以将另一个类 BaseCustomer声明为自己的友元,类 BaseCustomer 的所有成员函数就都可以访问类BaseProduct 对象的私有成员

#include<iostream>
#include<stdlib.h>
#include<string>

class BaseProduct
{
public:
	BaseProduct(){std::cout << "Here is BaseProduct Constructor!" << std::endl;}
	virtual ~BaseProduct(){std::cout << "Here is BaseProduct Destructor!" << std::endl;}
	virtual void initBaseProduct() 
	{
		iPrice = 101;
		iNum = 2;
		strDescription = "new Base product!";
	}
	
	friend class BaseCustomer;    //声明友元
private:
	int iPrice ;
	int iNum;
	std::string strDescription;
};

class BaseCustomer
{
public:
	BaseProduct baseProduct;
	
	BaseCustomer() {std::cout << "Here is BaseCustomer Constructor!" << std::endl;}
	virtual ~BaseCustomer() {std::cout << "Here is BaseCustomer Destructor!" << std::endl;}
	void getProductAttributes();

private:
	std::string strName;
};
//声明友元后,可直接调用类内私有成员
void BaseCustomer::getProductAttributes()
{
	baseProduct.initBaseProduct();
	std::cout << "BaseProduct iPrice:" << baseProduct.iPrice << std::endl;
	std::cout << "BaseProduct iNum:" << baseProduct.iNum << std::endl;
	std::cout << "BaseProduct strDescription:" << baseProduct.strDescription << std::endl;
}

int main()
{
	BaseCustomer baseCust;
	baseCust.getProductAttributes();
	return 0;
}

Here is BaseProduct Constructor!
Here is BaseCustomer Constructor!
BaseProduct iPrice:101
BaseProduct iNum:2
BaseProduct strDescription:new Base product!
Here is BaseCustomer Destructor!
Here is BaseProduct Destructor!
上一篇:Effective C++条款46:模板与泛型编程之(需要类型转换时请为模板定义非成员函数)


下一篇:「网易官方」极客战记(codecombat)攻略-沙漠-拦截-interception