C++ 类中会用到的关键字之-friend(virtual、override、friend、default、delete、final)
接上篇文章,此篇内容主要梳理friend相关内容,如有不合理地方请大家及时联系,多谢!
3.friend(友元)
c++中引入friend,引入目的如下:
- 对于没有继承关系的类,如果有关联,或需要访问类内私有成员的情况下,使用友元较为方便;
- 友元破坏了类的封装性和隐藏性,使用时需格外小心;
友元特性注意点 | 说明 |
---|---|
1 | 友元关系不能被继承 |
2 | 友元关系是单向的。若类B是类A的友元,类A不一定是类B的友元 |
3 | 友元关系具有非传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元 |
4 | 另:不能把其他类的私有成员函数或者其他类的虚函数声明为友元 |
1)友元函数
- 在定义一个类的时候,可以把一些函数(包括全局函数和其他类的非私有成员函数)声明为定义类的友元,这些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了
- 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数
友元函数例子:
#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!