Menu
Coddy logo textTech

friend関数とクラス

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/104。

ときどき、あなたのclassの外部にあるfunctionまたはclassが、そのprivateなmembersにアクセスする必要があります。これらのmembersをpublicにする代わりに、C++ではカプセル化を維持しながら選択的なアクセスを許可するために、friendキーワードが用意されています。

friend functionclass の内部で宣言されますが、その 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 である
    }
};

フレンド関係は相互的ではありません。EngineMechanic をフレンドとして宣言すると、MechanicEngine の private な members にアクセスできますが、その逆は成り立ちません。フレンドはクラス間の結合を強めるため、控えめに使用してください。フレンドは、operator のオーバーロードや密接に関連するヘルパー関数に最も役立ちます。

challenge icon

チャレンジ

簡単

MessageReader class が、SecureMessage class に保存された暗号化メッセージを読み取るための特別な access を必要とする、secure な messaging system を構築しましょう。これは friend functions と friend classes を使用するのに最適なシナリオです。

コードを整理するために、2つのファイルを作成します。

  • SecureMessage.h: private な message data を保存し、信頼されたエンティティに選択的な access を許可する SecureMessage class を 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 内で MessageReader class を Define します。

    • メッセージの private content に直接 access し、それを返す method readContent(const SecureMessage& msg)
    • 提供された key がメッセージの secretKey と matches するかを確認し、"Valid" または "Invalid" を返す method verifyKey(const SecureMessage& msg, int key)

    最後に、classes の後で decryptMessage friend function を Define します。

  • main.cpp: friend functions と friend classes の動作を実演します。input から message content、secret key、test key を読み取ります(それぞれ別の行に入力)。その後、次の処理を行います。
    • content と secret key を使用して SecureMessage を Create する
    • MessageReader object を 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 する

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;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ