C++ フレンドと演算子のオーバーロード

友元:

クラスメカニズムを採用した後、データの隠蔽とカプセル化を実現し、クラスのデータメンバーは一般的にプライベートメンバーとして定義され、メンバー関数は一般的にパブリックとして定義され、クラスと外部の間の通信インターフェースを提供します世界。ただし、クラスの一部ではなく、クラスのデータメンバーに頻繁にアクセスする必要があるいくつかの関数を定義する必要がある場合は、これらの関数を関数のフレンド関数として定義できます。フレンド関数に加えて、総称してフレンドと呼ばれるフレンド クラスもあります。フレンドの役割は、プログラムの実行効率を向上させること (つまり、型チェックやセキュリティ チェックなどに必要な時間のオーバーヘッドを削減すること) ですが、クラスのカプセル化と隠蔽を破壊し、非メンバー関数を許可します。クラスのプライベート メンバーにアクセスします。

フレンド機能:

 フレンド関数は、クラスのプライベート メンバーに直接アクセスできる非メンバー関数です。クラスの外で定義された通常の関数です. どのクラスにも属していませんが, クラス定義で宣言する必要があります. 宣言するときは, フレンドの名前の前にキーワード friend を追加するだけです. 形式は次のとおりです.次のように: フレンド型関数
       名 (仮パラメーター);

       フレンド関数の宣言は、クラスのプライベート部分に置くことも、パブリック部分に置くこともできますが、どちらにも違いはなく、いずれもクラスのフレンド関数であることを示しています。
       関数は複数のクラスのフレンド関数にすることができ、各クラスで個別に宣言するだけで済みます。
       フレンド関数を呼び出す方法と原則は、一般的な関数と同じです。

例えば:

メイン機能:

// youyuan.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "UncleWang.h"
#include "Family.h"

void GetUncle_Heart(const UncleWang& uncle);


int _tmain(int argc, _TCHAR* argv[])
{
	UncleWang uncle1;
	uncle1.Hobby();
	GetUncle_Heart(uncle1);
	getchar();

	return 0;
}

void GetUncle_Heart(const UncleWang& uncle)
{
	cout << "要俘获的人的心的名:" << uncle.name  << endl;
	cout << "要俘获的人的心的龄:" << uncle.age  << endl;
}



 #include "UncleWang.h"

#pragma once
#define NAMELEN 10
class UncleWang
{
	char* name;
	int age;
public:
	UncleWang();
	void Hobby();
	friend void GetUncle_Heart(const UncleWang& uncle);
	~UncleWang();
};

UncleWang.cpp

#include "stdafx.h"
#include "UncleWang.h"


void UncleWang::Hobby()
{
	cout << "我是隔壁" << this->name << ",我的年龄是:" << this->age << endl;
}

UncleWang::UncleWang()
{
	this->name = new char[NAMELEN];
	memset(this->name,0,NAMELEN);
	strcpy(this->name,"老王");
	this->age = 35;

}


UncleWang::~UncleWang()
{
	delete[] name;
}

これがフレンド機能です。

フレンドクラス:

  フレンド クラスのすべてのメンバー関数は、別のクラスのフレンド関数であり、別のクラスの非表示の情報 (プライベート メンバーと保護されたメンバーを含む) にアクセスできます。       
       クラスが別のクラスのプライベート メンバーにアクセスできるようにする場合は、そのクラスを別のクラスのフレンド クラスとして宣言できます。フレンド クラスを定義するためのステートメント形式は次のとおりです:
       フレンド クラス クラス名;
       ここで、フレンドとクラスはキーワードであり、クラス名はプログラムで定義されたクラスでなければなりません。

       たとえば、次のステートメントは、クラス B がクラス A のフレンド クラスであることを示しています: class
       A
       {               ...        public:               friend class B;               ...        };        上記の説明の後、クラス B のすべてのメンバー関数は、クラス B のフレンド関数です。クラス A は、クラス A のプライベート メンバーとプロテクト メンバーを取得できます。





       フレンドクラス使用時の注意
             (1) フレンド関係は継承できません。
             (2) 友情関係は一方通行であり、交換することはできません。クラス B がクラス A のフレンドである場合、クラスに対応するステートメントがあるかどうかによって、クラス A は必ずしもクラス B のフレンドであるとは限りません。
             (3) 友情関係は推移的ではありません。クラス B がクラス A のフレンドである場合、クラス C は B のフレンドであり、クラス C がクラス A のフレンドであるとは限らず、クラスに対応する宣言があるかどうかにも依存します。

A が B によってフレンド クラスとして宣言された後、A の関数内で、B がパラメーターである場合、B のメンバーおよびメンバー関数に直接アクセスできます。

例:

main.cpp

// youyuan.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "UncleWang.h"
#include "Family.h"

void GetUncle_Heart(const UncleWang& uncle);


int _tmain(int argc, _TCHAR* argv[])
{
	UncleWang uncle1;
	//uncle1.Hobby();
	//GetUncle_Heart(uncle1);
	Family f;
	uncle1.Uncle_visit_Family(f);
	getchar();

	return 0;
}

void GetUncle_Heart(const UncleWang& uncle)
{
	cout << "要俘获的人的心的名:" << uncle.name  << endl;
	cout << "要俘获的人的心的龄:" << uncle.age  << endl;
}



ファミリー.h

#pragma once
#define NAMELEN 10
class Family
{
	char* mother;
	char* father;
	char* me;
public:
	friend class UncleWang;
	Family();
	~Family();
	void Show();
};

ファミリー.cpp

#include "stdafx.h"
#include "Family.h"

void Family::Show()
{
	cout << "家庭成员:" << this->father<<" " << this->mother<<" " << this->me;
}

Family::Family()
{
	this->father = new char[NAMELEN];
	this->mother = new char[NAMELEN];
	this->me = new char[NAMELEN];
	strcpy(this->father,"父亲");
	strcpy(this->mother, "母亲");
	strcpy(this->me, "我");
}


Family::~Family()
{
	delete[] father;
}

 UncleWang.h

#pragma once
#define NAMELEN 10
#include "Family.h"
class UncleWang
{
	char* name;
	int age;
public:
	UncleWang();
	void Hobby();
	friend void GetUncle_Heart(const UncleWang& uncle);
	void Uncle_visit_Family(Family uncle);
	~UncleWang();
};

  UncleWang.cpp

#include "stdafx.h"
#include "UncleWang.h"


void UncleWang::Hobby()
{
	cout << "我是隔壁" << this->name << ",我的年龄是:" << this->age << endl;
}

void UncleWang::Uncle_visit_Family(Family f)
{
	cout << this->name << "拜访了" <<f.father << "一家"<<endl;
	cout << "f的一家:";
	f.Show();
}

UncleWang::UncleWang()
{
	this->name = new char[NAMELEN];
	memset(this->name,0,NAMELEN);
	strcpy(this->name,"老王");
	this->age = 35;

}


UncleWang::~UncleWang()
{
	delete[] name;
}

演算子のオーバーロード:

演算子のオーバーロードの本質は関数のオーバーロードですが、従うべき特定の規則があります。

二項演算子は、可能な限りフレンドとして宣言し、クラスの外で記述する必要があります。cin cout はフレンドとして宣言する必要があります。

最初のポイント:

ここで注意しなければならないのは、オーバーロードされたパラメーターの数が元のオペレーターの数と一致している必要があるということです。たとえば、+ 記号のパラメーターは、2 つの左加数と右加数です。次に、プラス記号をオーバーロードするときは、パラメーターとして左右に 2 つの加数があることも確認する必要があります。

2 番目のポイント:

通常の関数としてオーバーロードする場合:

単眼鏡: 右側のオペランドは仮パラメーターです;双眼鏡: 左側の仮パラメーターは演算子の左側のオペランドであり、右側の仮パラメーターは右側のオペランドです。

クラスのメンバー関数としてオーバーロードする場合:

オペレータ パラメータが 1 つしかない場合は、パラメータを記述する必要はありません。オペレータ パラメータが 2 つある場合は、パラメータを 1 つだけ記述する必要があります。

クラスのメンバー関数にはデフォルトで this ポインターがあるためです。クラス自体を直接指します。つまり、演算子のオーバーロードを記述すると、パラメーターの 1 つが既に this ポインターに含まれています。

単項演算子。通常、単項演算子のパラメーターは右側にあるため、これは演算子の右側のパラメーターを指します。

二項演算子、これは演算子の左側のパラメーターを指します。

例として、2 つの時間クラス a と b が減算される場合のマイナス記号を取り上げます。a - b の場合、this ポインターは a を指し、そうでない場合は b を指します。関数を宣言するときは、適切なパラメーターを記述するだけです。a - b については、int operator-(Time b); と書くだけで済みます。

もちろん、単項演算子にはパラメーターが 1 つしかなく、パラメーターは this によってポイントされるため、パラメーターを宣言する必要はありません。

(2). 戻り値
演算子の戻り値の型は、オーバーロードされた関数の機能に依存します。

たとえば、a + b の機能は加数を取得することであり、戻り値は a+b の値です。a += b の機能は、a の値を変更することです. パラメータ a の値が変更されるため、値を返す必要はありません.

また、複数の操作をサポートする演算子が必要な場合は、値を返す必要もあります。たとえば、ストリーム挿入演算子 <<. cout << a << b << c のように、複数回挿入する必要がある場合があります。後続のストリーム挿入を容易にするために、ストリーム ostream 自体を返す必要があります。

<< >> 演算子はオーバーロードされています。

#include <iostream>
#include <string> 
#include <cstring> 
using namespace std;
class String
{
private:
    string str;   
public:
	String(string s){str=s;}
	char & operator[](int i);
	friend ostream & operator<<(ostream & cout, const String & st);
    friend istream & operator>>(istream & cin, String & st);
};

char &String::operator[](int i)
{
    return str[i];
}
ostream &operator<<(ostream & cout, const String &st)
{
    cout << st.str;
    return cout;
}

istream &operator>>(istream & cin, String &st)
{
    char temp[40];
    is.get(temp, 40);
    if (cin)
        st = temp;
    while (cin && cin.get() != '\n')
        continue;
    return cin;
}

 = 演算子のオーバーロード

#include <cstring>
#include <sstream>
class HugeInteger{
public:
	HugeInteger& operator=(const HugeInteger &h);
private:
    string str;
};

HugeInteger& HugeInteger::operator=(const HugeInteger &h)
{
    this->str=h.str;
    return *this;
}

おすすめ

転載: blog.csdn.net/makabaka12138/article/details/128538129