普通友元函数
-
用friend修饰的函数
-
友元只是提供一个场所,赋予对象能够打破类的权限限定(无视权限)
-
无视权限不是说可以忽视掉原来的规则,类中的数据成员必须通过对象去调用
-
友元函数在一定程度上打破了类的封装性
-
友元函数可以在类中声明,类中实现|类外实现
在类外实现友元函数需要注意:
-
不需要类名限定
-
不需要friend关键字
调用友元函数需要注意:
-
不需要类名限定
-
不需要对象
-
没有权限限制
无参普通函数:在类中声明,在类中实现需要在最前面声明一下--->未声明 & 未定义的标识符
void printData(); //告诉编译器有这个函数,函数在类中的定义实现
友元函数不属于类,在类中实现不能直接访问数据
解决方案:
-
在友元函数中构建对象的方式访问数据,无视权限--->访问保护 & 私有属性
-
传参的方式传入对象的引用
void printData();
class MM
{
public:
MM(string name, int age) :name(name), age(age) {}
void print()
{
cout <<name << "\t" <<age<< endl;
}
friend void printData()
{
cout<<name<<"\t"<<age<<endl; //报错:不属于类,不能直接访问成员
MM mm("好朋友",29); //构建一个对象的方式
//友元函数提供一个场所,在函数中让对象无视权限,可以访问保护&私有
cout <<mm.name << "\t" <<mm.age<< endl;
}
protected:
string name;
private:
int age;
friend void printData2(MM& mm); //传参的方式
};
void printData2(MM& mm) //不需要friend修饰,不需要类名限定
{
cout<<mm.name<<"\t"<<mm.age<<endl;
}
int main()
{
MM mm("小明",12);
mm.print(); //普通函数受权限限定,需要指定对象
printData2(mm); //可以直接调用,不需要管类中的权限
printData();
return 0;
}
/*输出*/
小明 12
小明 12
好朋友 29
普通函数和友元函数的区别
普通函数没法直接调用类中的数据成员,存在权限限定问题
友元函数不受权限限定,在外面可以直接调用类中的数据成员
//普通函数
void printMM()
{
cout<<mm.name<<"\t"<<mm.age<<endl; //报错:成员已声明,不可访问
}
以另一个类的成员函数充当友元函数(注意写法顺序问题)
一个类(B类)的成员函数充当另一个类(A类)的友元函数,实现顺序如下:
-
B 类
-
A 类
-
A类的友元函数(B类的成员函数)一定是在B、A类下面实现,在A类中声明为友元,在类外实现
-
解决未定义class A & class B问题
比喻:有一个人,再来一个人,才能描述他们之间的关系
class B
{
public:
void printA();
};
class A
{
public:
friend void B::printA(); //B类的成员函数充当A类的友元函数
protected:
string name= "A";
};
//成员函数实现,一定是在另一个类的下面实现
void B::printA()
{
A a;
cout << a.name<< endl; //可以无视权限限定
}
int main()
{
B b;
b.printA();
return 0;
}
/*输出*/
A
B类中的其他函数不是A类的友元函数,不能无视权限限定
class B
{
public:
void printData();
};
void B::printData()
{ //B类的一个成员函数(未声明为A类的友元函数)
A a;
cout << a.name<< endl; //报错:不能访问,没有声明为A类的友元函数|不是A类的友元函数
}