C++友元
Posted libinkai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++友元相关的知识,希望对你有一定的参考价值。
友元是C++提供的一种破坏数据隐蔽和封装的机制
1.友元函数
友元函数是在类中使用关键字friend修饰的非成员函数
1.1友元普通函数
定义与概念
- 友元函数是一个普通的函数
友元普通函数在实现时,不需要类名的限定;在调用时,也不需要由实例来调用
示例代码
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point(int x = 0,int y = 0):x(x),y(y){}
int getX(){ return x;}//内联函数
int getY(){ return y;}
void showData();
friend float dist(Point &p1,Point &p2);//声明友元函数
private:
int x,y;
};
//普通成员函数的实现,需要类名限定
void Point::showData(){
cout << "x: " << x << ", y: " << y << endl;
}
//因为友元函数是非成员函数,所以不需要类名限制
float dist(Point &p1,Point &p2){
double x = p1.x - p2.x;
double y = p1.y - p2.y;
return static_cast<float>(sqrt(x*x + y*y));
}
int main()
{
Point p1(1,1),p2(4,5);
p1.showData();
p2.showData();
//调用友元普通函数时,也不需要由类的实例来调用
cout << "the distance is : " << dist(p1,p2) << endl;
return 0;
}
1.2友元成员函数
定义与概念
- 友元函数是其它类的成员函数
必须先定义包含成员函数的类(比如说A),再在另外一个类(比如说B)中将该成员函数声明为友元函数。此时虽然这个友元函数是A的成员函数,该友元函数仍然称为非成员函数(对于B来说)
示例代码
#include <iostream>
#include <cmath>
using namespace std;
//前向引用声明,否则报错 error: 'Point' does not name a type
class Point;
class Line{
public:
//这时不能使用这样的形式进行初始化:Line(Point p1,Point p2):p1(p1),p2(p2){}
//因为此时Point的结构尚未定义,error: field 'p1' has incomplete type
Line(Point p1,Point p2);
Point& getP1(); //把引用当做函数返回值
Point& getP2();
float dist();
private:
//不可以这样定义成员变量:Point p1,p2;因为此时Point结构尚不完善
Point &rp1,&rp2;//类(引用)的组合
};
class Point{
public:
Point(int x = 0,int y = 0):x(x),y(y){}
int getX(){ return x;}//内联函数
int getY(){ return y;}
void showData();
//声明友元成员函数
friend float Line::dist();
private:
int x,y;
};
void Point::showData(){
cout << "x: " << x << ", y: " << y << endl;
}
//Line类函数的延迟实现开始
//当一个类的成员变量是引用时,需要在初始化列表中初始化引用
//否则报错:error: uninitialized reference member
Line::Line(Point p1,Point p2):rp1(p1),rp2(p2){}
Point& Line::getP1(){
return rp1;
}
Point& Line::getP2(){
return rp2;
}
float Line::dist(){
double x = rp1.x - rp2.x;
double y = rp1.y - rp2.y;
return static_cast<float>(sqrt(x*x + y*y));
}
//Line类函数的延迟实现结束
int main()
{
Point p1(1,1),p2(4,5);
p1.showData();
p2.showData();
Line line(p1,p2);
cout << "the distance is : " << line.dist() << endl;
return 0;
}
2.友元类
定义与概念
示例代码
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point(int x = 0,int y = 0):x(x),y(y){}
int getX(){ return x;}//内联函数
int getY(){ return y;}
void showData();
//声明友元类,否则编译不通过,error: 'int Point::x' is private
friend class Line;
private:
int x,y;
};
void Point::showData(){
cout << "x: " << x << ", y: " << y << endl;
}
class Line{
public:
Line(Point p1,Point p2):p1(p1),p2(p2){}
Point getP1(){ return p1;}
Point getP2(){ return p2;}
float dist();
private:
Point p1,p2;//类的组合
};
float Line::dist(){
double x = p1.x - p2.x;
double y = p1.y - p2.y;
return static_cast<float>(sqrt(x*x + y*y));
}
int main()
{
Point p1(1,1),p2(4,5);
p1.showData();
p2.showData();
Line line(p1,p2);
cout << "the distance is : " << line.dist() << endl;
return 0;
}
3.友元的性质
- 友元关系是不能传递的,如A是B的友元,B是C的友元,但A不是C的友元
- 友元关系是单向的,A是B的友元,A可以访问B的私有属性,反之不成立
友元关系是不被继承的,A是B的友元,但A的派生类不是B的友元
4.总结
- 友元是一种破坏数据隐蔽和封装的机制,这是它的用处也是它的坏处。应该尽量避免使用友元
示例代码
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point(int x = 0,int y = 0):x(x),y(y){}
int getX(){ return x;}//内联函数
int getY(){ return y;}
void showData();
float dist(Point p);
private:
int x,y;
};
void Point::showData(){
cout << "x: " << x << ", y: " << y << endl;
}
//通过这样的方式,可以避免使用友元
float Point::dist(Point p){
double x = p.x - this->x;
double y = p.y - this->y;
return static_cast<float>(sqrt(x*x + y*y));
}
int main()
{
Point p1(1,1),p2(4,5);
p1.showData();
p2.showData();
cout << "the distance is : " << p1.dist(p2) << endl;
return 0;
}
5.补充
5.1前向声明
- 在C++里面可以声明一个类而不定义它。这个声明被称为前向声明(forward declaration)。
- 在声明之后,定义之前,这个类是一个不完全类型(incompete type),即已知它是一个类型,但不知道包含哪些成员,具有哪些操作。
- 不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。
以上是关于C++友元的主要内容,如果未能解决你的问题,请参考以下文章