1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

内部クラス? friend? っていう気の迷いメモ

Last updated at Posted at 2024-06-14

おことわり

頭悪い初心者のメモです.

謎の話

class Yclass Zclass X が使う何らかの実装として作られた.

//[X.h]
class Y;
class Z;

class X
{
    ...
private:
    Y *m_pY;
    Z *m_pZ;
};

この YZ の具体的な定義というのはどこに書くのか?
こいつらのコードが小規模ならば

//[X.cpp]
#include "X.h"

//じゃあここに書くし
class Y { ... };  //Yの定義
class Z { ... };  //Zの定義

//...以降,Xの実装

とかすれば,とりあえず他所からこの YZ を使うことはできない(…と思う).
しかし,コード量的に割と邪魔な場合,Y.hY.cpp とかに分けたくなる.

//[X.cpp]
#include "X.h"

#include "Y.h"  //別のところに実装しました
#include "Z.h"

//...以降,Xの実装

でもそうすると,

//[どこか別のコード]
#include "Y.h"  //←ヒャッハー! Yを使っちゃうぜ!
...

とかやれちゃう.何か嫌だ.

そしたら,「他所で使う想定じゃねーから」という物は「これらは X の実装の一部分なので」という話にしておくべきなのか?

class X
{
private:
    class Y;
    class Z;
};

これなら他所で #include "Y.h" とかしてみたところで Y を使おうとすればコンパイラ様がブチギレて阻止してくれる.
しかしこういうスタイル↓というのも考えられるのではあるまいか?

//「YやZを内部クラスとして定義する」だけのやつを別途用意して,
//Xはそいつの友達だということにする.
class Impls
{
    friend class X;
private:
    Impls() = delete;   //このImplsクラス自体はただの入れ物.インスタンスを作れない.
private:
    //これらはXからは使える
    class Y;
    class Z;
};

YZ を使えるやつを friend で登録する的な.

一番最初の状態では,YZX の内部クラスというわけじゃなかったのだから,こっちの方が元々のあるべき姿(?)に近い…のだろうか?

追記

しかし,本当にそこまでして頑なに「使わせない使えない」を達成する必要があるのかい?
例えば,YZ をいかにも「内部実装ですが何か?」みたいな名称の名前空間にでも突っ込んで,「他所で使う想定じゃねーから」っていう雰囲気だけ示しておけばそれで良くね?

……と,イマジナリーフレンドが脳内に直接意見してくるのであった.

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?