友元関数、クラス、演算子の再ロード

14448 ワード

友元関数の紹介
プログラム設計でクラスAを加えてクラスBのプライベートメンバーやプライベート関数にアクセスしようとする場合,プログラムのカプセル化性を維持し,共有性を持たせるために,友元クラスや友元関数を用いた.
友元類


class A
{ 
    friend class B ;
public :
    void  Display() { cout << x << endl ; } ;
private :
    int  x ;
} ;
//    A         B,   B    A          
class  B
{ 
public :
    void Set ( int i ) { Aobject . x = i ; } 
    void Display ()  { Aobject . Display () ; }
     //    A     
private :
    A  Aobject ;//    A   
} ;
void main()
{
    B  Bobject ;
    Bobject . Set ( 100 ) ;
    Bobject . Display () ;
    system("pause");
}

ゆうげんかんすう
友元関数の応用は比較的に多くて、よく使う場合:1.演算子をリロードする場合は、友元を使用する必要があります.2.2つのクラスがデータを共有する必要がある場合.
class Test2
{
public:
    //        :               .
    //         ,                  。
    friend int OpMem(Test2 *p, int a); //    ,       ,           
    Test2(int a, int b)
    {
        this->a = a;
        this->b = b;
    }
    int getA()
    {
        return this->a;
    }
protected:

private:
    int a ;
    int b;
};


int OpMem(Test2 *p, int a)
{
    p->a = a;//        
    return 0;
}

void main()
{
    Test2 t1(1, 2);
    t1.getA();
    OpMem(&t1, 10);//        ,            
    system("pause");
}

演算子の再ロード
演算子リロードとは、クラスの多様性(1つの関数名に複数の意味がある)を実現するために、演算子がクラスと結合し、新しい意味を生成することです.演算子のリロードをどのように実現しますか?方法:クラスのメンバー関数または友元関数(クラス外の一般的な関数)ルール:再ロードできない演算子は.と.*と?:とsizeof友元関数とメンバー関数の使用の場合:一般的には、一元演算子はメンバー関数、二元演算子は友元関数を使用することをお勧めします.1、演算子の操作はクラスオブジェクトの状態を変更する必要がある場合は、メンバー関数を使用します.左の値の操作が必要な場合は数の演算子(=,+=,++)2、演算時、数とオブジェクトの混合演算の場合は、友元3、二元演算子のうち、最初のオペランドが非オブジェクトの場合は、友元関数を使用する必要があります.入出力演算子<>の具体的なルールは次のとおりです.
演算子
推奨される使用方法
すべての一元オペレータ
メンバー関数
= 、()、[]、->
メンバー関数でなければなりません
+=、-=、/=等帯=の演算子
メンバー関数
+、-、*などの二次演算子
ゆうげんかんすう
<<>>
友元関数でなければなりません
関数と戻り値
  • 戻り値が=左に表示され、左値(右値としてもよい)として表示される場合は、非const参照である必要があります.
  • 戻り値が=右に表示された場合、右の値としてのみ使用でき、const参照またはconst値(読み取り専用)が返されます.
  • 演算子の例
    +および-演算子の再ロード
    #include 
    using namespace std;
    class PointTest
    {
    private: 
        double pointX;  
    public:
        PointTest(int x1)
        {
            pointX=x1;
    
        }
        void PrintResult();
        const PointTest operator +(const PointTest &obj);//           
        friend const PointTest operator -(const PointTest &obja,const PointTest & objb);//    
    
    };
    #pragma region     
    
    const PointTest PointTest::operator+(const PointTest &obj)
    {
        return PointTest(this->pointX + obj.pointX);
    }
    
    void PointTest::PrintResult()
    {
        cout<<this->pointX<//system("pause");
        getchar();
    }
    #pragma endregion
    //      +
     const PointTest operator-(const PointTest &obja,const PointTest & objb)
     {
        return PointTest(obja.pointX-objb.pointX);
     }
    
    int main()
    
    {
        PointTest a(1);
        PointTest b(2);
        PointTest c = a+b;//      
        c.PrintResult();
        c =c-b;
        c.PrintResult();
        a-1;//  ,         , 1    ,        
        a+1;//  ,       const  ,     
        1-a;
        //1+a;       ,           ,                   
    
    
    }

    1、+-はすべて=号の右側に現れるため、c=a+bのように、つまり1つの右の値を返して、const型の値2を返すことができて、後のいくつかの式は討論して、数とオブジェクトの混合演算子の情況で、一般的にこのような情況が現れて、よく友元関数を使います
    単項演算子+、–
    class Point    
    {    
    private:    
        int x;   
    public:    
        Point(int x1)  
        {   x=x1;}    
        Point operator++();//          
        const Point operator++(int x); //        const      
        friend Point operator--(Point& p);//      --  
        friend const Point operator--(Point& p,int x);//        const      
    };    
    
    Point Point::operator++()//++obj  
    {  
        x++;  
        return *this;  
    }  
    const Point Point::operator++(int x)//obj++  
    {  
        Point temp = *this;  
        this->x++;  
        return temp;  
    }  
    Point operator--(Point& p)//--obj  
    {  
        p.x--;  
        return p;  
             //    (--obj)         ,      *this       ,              
    }  
    const Point operator--(Point& p,int x)//obj--  
    {  
        Point temp = p;  
        p.x--;  
        return temp;  
             //     obj--        int     ,           
    }  
    int main()
    {
    Point b(2);  
    a++;//        operator++(0),       
    ++a;//        operator++(),       
    b--;//        operator--(0),       
    --b;//        operator--(),       
    cout<operator ++(2);//        operator ++(2),       
    cout<operator ++();//        operator ++(),       
    cout<<operator --(b,2);//        operator --(2),       
    cout<<operator --(b);//        operator --     
    } 

    前置++(++a)と後置++(a+++)では、前後接尾辞は関数名(operator+)のみで区別できず、パラメータ区分のみがあり、ここでは虚パラメータint xを導入し、xは任意の整数であってもよい.リロード演算子[]は、ここではオブジェクト参照を返すことについて説明します.
    class Point    
    {    
    private:    
        int x[5];   
    public:    
        Point()  
        {  
            for (int i=0;i<5;i++)  
            {  
                x[i]=i;  
            }  
        }   
        int& operator[](int y);  //          
    };    
    int& Point::operator[](int y)  
    {  
        static int t=0;  
        if (y<5)  
        {  
            return x[y];  
        }  
        else  
        {  
            cout<<"    ";  
            return t;  
        }     
    }  
    
    
    int main()
    {
    Point p;
    int a = p[3];//     ,     ,      。
    a[2] = 3;//         ,       ,             ,          。
    }

    演算子[]のリロード方法:メンバー関数のみでリロードできます.関数名:operatorパラメータテーブル:パラメータが1つのみで、通常は整数ですが、文字列(下付きとみなされます)としても使用できます.≪戻り値|Return Value|emdw≫:返される値は左または右のいずれかで、戻り参照を使用する必要があります.難点リロード演算子<>
          class Point    
    {    
    private:    
        int x;   
    public:    
        Point(int x1)  
        {   x=x1;}   
        friend ostream& operator<cout,const Point& p);//        <
        friend istream& operator>>(istream& cin,Point& p);//        >>       
    }; 
    //  <
    ostream& operator<cout,const Point& p)  
    {  
        cout<return cout;  
    }  
    istream& operator>>(istream& cin,Point& p)  
    {  
        cin>>p.x;  
        return cin;  
    }
    Point a(1);  
    Point b(2);  
    cin>>a>>b;  
    cout<

    構文:リロード方法:友元関数のみを使用してリロードし、3つの参照を使用できます&
    関数名:出力フロー:operator<入力フロー:operator>(パラメータテーブル)
  • 出力ストリーム出力ストリーム:出力ストリームostream&とオブジェクトの最初のオペランドcoutの2つのパラメータでなければなりません.ファイルiostreamに定義され、標準クラスタイプostreamのオブジェクトの参照です.例:ostream&cout,const Point&p ostream&operator<
  • 入力ストリームは、2つのパラメータでなければなりません.入力ストリームostream&オブジェクトの最初のオペランドはcinです.ファイルiostreamで定義されています.実際には、instream&cin、const Point&p istream&operator>(istream&cin、オブジェクト参照)メンバー関数には、オブジェクト呼び出しが必要です.最初のパラメータはクラスのオブジェクトでなければなりませんが、<>最初のパラメータはストリームのオブジェクト参照です.メンバー関数
  • は使用できません.