friend関数とクラス
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/104。
ときどき、あなたのclassの外部にあるfunctionまたはclassが、そのprivateなmembersにアクセスする必要があります。これらのmembersをpublicにする代わりに、C++ではカプセル化を維持しながら選択的なアクセスを許可するために、friendキーワードが用意されています。
friend function は class の内部で宣言されますが、その class のメンバーではありません。class のプライベートメンバーおよび保護されたメンバーにアクセスできます。
class Box {
double width;
public:
Box(double w) : width(w) {}
// printWidth を friend として宣言
friend void printWidth(const Box& b);
};
// フレンド関数の定義 - メンバー関数ではない
void printWidth(const Box& b) {
std::cout << b.width; // プライベートメンバーにアクセスできる
}printWidth がスコープ解決演算子なしで class の外部に定義されていることに注意してください。これは、特別なアクセス権限を持つ通常の関数です。
class 全体を friend にすることもでき、すべての member functions に private members への access を許可できます。
class Engine {
int horsepower;
friend class Mechanic; // Mechanic は private メンバーにアクセスできる
public:
Engine(int hp) : horsepower(hp) {}
};
class Mechanic {
public:
void diagnose(const Engine& e) {
std::cout << e.horsepower; // 許可されている - Mechanic は friend である
}
};フレンド関係は相互的ではありません。Engine が Mechanic をフレンドとして宣言すると、Mechanic は Engine の private な members にアクセスできますが、その逆は成り立ちません。フレンドはクラス間の結合を強めるため、控えめに使用してください。フレンドは、operator のオーバーロードや密接に関連するヘルパー関数に最も役立ちます。
チャレンジ
簡単MessageReader class が、SecureMessage class に保存された暗号化メッセージを読み取るための特別な access を必要とする、secure な messaging system を構築しましょう。これは friend functions と friend classes を使用するのに最適なシナリオです。
コードを整理するために、2つのファイルを作成します。
SecureMessage.h: private な message data を保存し、信頼されたエンティティに選択的な access を許可するSecureMessageclass を Define します。class には次の要素を含めます。- Private members:
content(string) およびsecretKey(int) - content と secret key を受け取る constructor
MessageReaderを friend class として Declare し、private members に access できるようにするdecryptMessage(const SecureMessage& msg, int key)という friend function を Declare する。提供された key が secret key と matches する場合のみ content を返し、それ以外の場合は"Access Denied"を返す
次に、同じ header file 内で
MessageReaderclass を Define します。- メッセージの private
contentに直接 access し、それを返す methodreadContent(const SecureMessage& msg) - 提供された key がメッセージの
secretKeyと matches するかを確認し、"Valid"または"Invalid"を返す methodverifyKey(const SecureMessage& msg, int key)
最後に、classes の後で
decryptMessagefriend function を Define します。- Private members:
main.cpp: friend functions と friend classes の動作を実演します。input から message content、secret key、test key を読み取ります(それぞれ別の行に入力)。その後、次の処理を行います。- content と secret key を使用して
SecureMessageを Create する MessageReaderobject を Create する- reader の
readContent()method を使用して"Reader access: <content>"を Print する - test key を使用して
verifyKey()を呼び出し、"Key verification: <result>"を Print する - test key を使用して friend function を呼び出し、
"Decrypt with test key: <result>"を Print する - 元の secret key を使用して friend function を呼び出し、
"Decrypt with correct key: <result>"を Print する
- content と secret key を使用して
friend functions は scope resolution operator なしで class の外部に Define されることに注意してください。つまり、特別な access privileges を持つ通常の functions です。friend である MessageReader class は、そのすべての methods 内で SecureMessage の private members に直接 access できます。
std::stoi() を使用して、key の input を strings から integers に変換します。#include "SecureMessage.h" を使用して、main.cpp に header file を Include してください。
自分で試してみよう
#include <iostream>
#include <string>
#include "SecureMessage.h"
using namespace std;
int main() {
// 入力を読み取る
string messageContent;
string secretKeyStr;
string testKeyStr;
getline(cin, messageContent);
getline(cin, secretKeyStr);
getline(cin, testKeyStr);
int secretKey = stoi(secretKeyStr);
int testKey = stoi(testKeyStr);
// TODO: コンテンツとシークレットキーでSecureMessageを作成する
// TODO: MessageReaderオブジェクトを作成する
// TODO: Print "Reader access: <content>" using readContent()
// TODO: Print "Key verification: <result>" using verifyKey() with test key
// TODO: Print "Decrypt with test key: <result>" using decryptMessage with test key
// TODO: Print "Decrypt with correct key: <result>" using decryptMessage with secret key
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタパラメータ付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ徹底解説Rule of Three / Five / Zero復習 - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () の演算子オーバーロード型変換演算子復習 - Matrixクラス自分で練習してみよう: C++オンラインコンパイラ