C/C++友元
5814 ワード
(1)概念
(1)なぜ友元を使うのか
クラス間のデータ共有を実現する際、システムのオーバーヘッドを低減し、効率を向上させる.クラスAの関数がクラスBのメンバー(たとえば、スマートポインタクラスの実装)にアクセスする場合、クラスAの関数はクラスBの友元関数である.
すなわち、他のクラスのメンバー関数がクラスのプライベート変数に直接アクセスできるように、外部のクラスまたは関数がクラスのプライベート変数と保護変数にアクセスし、2つのクラスが同じ関数を共有できるようにします.
実際には、(1)演算子をリロードする場合、(2)2つのクラスがデータを共有する場合、(2)演算子をリロードする必要がある場合の2つのケースがあります.
利点:効率を高めることができて、表現が簡単で、はっきりしています;欠点:友元関数はパッケージメカニズムを破り、できるだけ友元関数を使用しないで、やむを得ない場合を除いて友元関数を使用しない.
友元関数はクラス外の関数であるため、その宣言はクラスのプライベートセグメントまたは共通セグメントに置くことができ、区別がなく、オブジェクトやポインタを通過する必要がなく、友元関数を直接呼び出すことができます.
(2)友元分類
(1)一般クラスのメタ関数
(2)友元クラス(すべてのメンバー関数が友元関数)
(3)詳細な例を見る
(4)部分オペレータリロードなぜ友元を使用するのか
書き方フォーマット:戻り値operator演算子(パラメータリスト){}
オペレータのリロードは優先度を変更せず、操作数の数は変更されません.
演算子を再ロードする場合、関数宣言はクラス内とクラス外で区別され、例えば+-*/など2つのオペランドを必要とする演算子;
(1)クラス外で宣言:クラスの外部で宣言された場合、パラメータリストは2つのパラメータであり、最初のパラメータは演算子の左側のオペランドであり、2番目のパラメータはオペレータの右側のオペランドである.
(2)クラス内、すなわちクラスのメンバー関数を宣言する.
1番目のオペランドはオペレータを呼び出すオブジェクトの参照であり、2番目のオペランドは伝達されたパラメータである.
だから重荷<
最初のパラメータは、演算子の最初のオペランドですが、クラスオブジェクトではありません.したがって、クラス演算子がリロードされたときにクラスの内部に書き込まれると、クラス内のpublic以外の変数または関数にアクセスするために、友元関数として宣言する必要があります.
(1)なぜ友元を使うのか
クラス間のデータ共有を実現する際、システムのオーバーヘッドを低減し、効率を向上させる.クラスAの関数がクラスBのメンバー(たとえば、スマートポインタクラスの実装)にアクセスする場合、クラスAの関数はクラスBの友元関数である.
すなわち、他のクラスのメンバー関数がクラスのプライベート変数に直接アクセスできるように、外部のクラスまたは関数がクラスのプライベート変数と保護変数にアクセスし、2つのクラスが同じ関数を共有できるようにします.
実際には、(1)演算子をリロードする場合、(2)2つのクラスがデータを共有する場合、(2)演算子をリロードする必要がある場合の2つのケースがあります.
利点:効率を高めることができて、表現が簡単で、はっきりしています;欠点:友元関数はパッケージメカニズムを破り、できるだけ友元関数を使用しないで、やむを得ない場合を除いて友元関数を使用しない.
友元関数はクラス外の関数であるため、その宣言はクラスのプライベートセグメントまたは共通セグメントに置くことができ、区別がなく、オブジェクトやポインタを通過する必要がなく、友元関数を直接呼び出すことができます.
(2)友元分類
(1)一般クラスのメタ関数
class INTEGER
{
friend void Print(const INTEGER& obj);//
};
void Print(const INTEGER& obj)
{
}
void main()
{
INTEGER obj;
Print(obj);//
}
(2)友元クラス(すべてのメンバー関数が友元関数)
class girl;
class boy
{
public:
void disp(girl &);
};
// disp() boy , girl
void boy::disp(girl &x)
{
// , boy disp , girl , girl
cout<<"girl's name is:"<",age:"<class girl
{
private:
char *name;
int age;
// boy girl
friend class boy;
};
(3)詳細な例を見る
//point.h
class Point {
private:
int x, y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
void getXY();
friend int distance(Point &a, Point &b);
friend class You;
};
class You {
public:
double Multi(Point &a) {
return a.x * a.y + 1;
}
};
void showPoint();
//point.cpp
#include
#include "point.h"
using std::cout;
using std::endl;
void Point::getXY() {
cout << x << ":" << y << endl;
}
int distance(Point &a, Point &b) {
int x = a.x + b.x;
int y = b.y + b.y;
return x + y;
}
void showPoint() {
Point p1(2, 3), p2(4, 5);
p1.getXY();
cout << distance(p1, p2) << endl;
You you;
cout << you.Multi(p1) << endl;
}
(4)部分オペレータリロードなぜ友元を使用するのか
書き方フォーマット:戻り値operator演算子(パラメータリスト){}
オペレータのリロードは優先度を変更せず、操作数の数は変更されません.
演算子を再ロードする場合、関数宣言はクラス内とクラス外で区別され、例えば+-*/など2つのオペランドを必要とする演算子;
(1)クラス外で宣言:クラスの外部で宣言された場合、パラメータリストは2つのパラメータであり、最初のパラメータは演算子の左側のオペランドであり、2番目のパラメータはオペレータの右側のオペランドである.
classType operator+(classType& left, classType& right);
(2)クラス内、すなわちクラスのメンバー関数を宣言する.
classType operator+(classType& right);
1番目のオペランドはオペレータを呼び出すオブジェクトの参照であり、2番目のオペランドは伝達されたパラメータである.
だから重荷<
ostream& operator<const classType& obj);
最初のパラメータは、演算子の最初のオペランドですが、クラスオブジェクトではありません.したがって、クラス演算子がリロードされたときにクラスの内部に書き込まれると、クラス内のpublic以外の変数または関数にアクセスするために、友元関数として宣言する必要があります.
friend ostream& operator<const classType& obj);
//
std::ostream & operator<std::ostream & os, const Time & t) {
os << t.hours << " hours, " << t.minutes << " minutes";
return os;
}