モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

クラスの相互参照 (C++をもう一度)

モーダルを閉じる

ステッカーを選択してください

お支払い手続きへ
モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2014/12/23
最終更新最終更新
2018/09/07
記事区分記事区分
一般公開

目次

    低レイヤーのプログラミングとOS開発が趣味。C言語を使っています。

    サンプルコード

    クラスのメンバ関数のフレンド登録などを行うためにクラスの相互参照が発生することがあります。このような場合はクラスの不完全型を宣言することで解決します。

    my_class.h

    #ifndef MY_CLASS_H_20141223_0137_
    #define MY_CLASS_H_20141223_0137_
    
    #include "my_friend_class.h" // 「1.」の場合は不完全型 <*↓> で十分なため不要
    
    class MyClass {
        // 関連事項: フレンド関数
    
        // 1. フレンドクラスを登録する場合
        // (メンバ関数すべてが MyClass の private,protected を閲覧可能)
        // friend class MyFriendClass; // 不完全型の宣言を兼ねる <*>
    
        // 2. 特定のメンバ関数のみをフレンド登録する場合
        friend MyClass* MyFriendClass::CreateMyClass(int intval) const;
    
    public:
        void Show() const;
    
    private: // コンストラクタ関連、すべて private
        MyClass(int intval);
        MyClass(const MyClass&); // 敢えて cpp で実装しない技 (呼び出すとエラーにできる)
        void operator=(const MyClass&); // (同上)
        int m_intval;
    };
    
    #endif // #ifndef MY_CLASS_H_20141223_0137_
    

    my_class.cpp

    #include "my_class.h"
    #include <iostream>
    using namespace std;
    
    MyClass::MyClass(int intval) :
        m_intval(intval)
    {
    }
    
    void MyClass::Show() const {
        cout << m_intval << endl;
    }
    

    my_friend_class.h

    #ifndef MY_FRIEND_CLASS_H_20141223_0137_
    #define MY_FRIEND_CLASS_H_20141223_0137_
    
    class MyClass; // 不完全型
    // こちらで #include "my_class.h" してしまうと、お互いに
    // include していることになり、無限 include が発生してエラー
    // (ifndef によって無限 include は回避できますが、そうすると
    //  "my_class.h" 内で "my_friend_class.h" を事実上 include
    //  できずにエラーになることが、少し考えると分かります)
    // 不完全型 MyClass の宣言によってこれを回避できます。
    
    class MyFriendClass {
    public:
        MyClass* CreateMyClass(int intval) const; // 最低でも不完全型の宣言が必要
                                                  // (完全な宣言までは知る必要がない)
    };
    
    #include "my_class.h" // エラー回避のため MyFriendClassの完全な宣言の後で include します。
    // ちなみにこの include は MyFriendClass の完全な宣言のためではなく my_friend_class.cpp
    // における MyFriendClass::CreateMyClass の実装のためです。
    
    #endif // #ifndef MY_FRIEND_CLASS_H_20141223_0137_
    

    my_friend_class.cpp

    #include "my_friend_class.h"
    
    MyClass* MyFriendClass::CreateMyClass(int intval) const {
        return new MyClass(intval); // new するためには MyClass 型の完全な宣言が必要
    }
    

    main.cpp

    #include "my_friend_class.h"
    // #include "my_class.h" // ← なくてもよい
    #include <iostream>
    using namespace std;
    
    int main() {
        MyFriendClass f;
        MyClass* obj = f.CreateMyClass(1);
        obj->Show(); //=> 1
        return 0;
    }
    

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    %.o: %.cpp
    $(CC) $(CFLAGS) -o $@ -c $<
    
    ALL: main.o my_class.o my_friend_class.o
    $(CC) $(CFLAGS) -o main main.o my_class.o my_friend_class.o
    
    my_class.o: my_class.h
    my_friend_class.o: my_friend_class.h
    
    Likeボタン(off)0
    詳細設定を開く/閉じる
    アカウント プロフィール画像

    低レイヤーのプログラミングとOS開発が趣味。C言語を使っています。

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    >>さらに詳しくステッカーを贈る
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      ログインする

      関連記事