ネストされたクラス
クラス内にネストされたクラスには、通常は欠陥と見なされるいくつかの副作用があります(純粋なアンチパターンではない場合)。
次のコードを想像してみましょう:
class A
{
public :
class B { /* etc. */ } ;
// etc.
} ;
あるいは:
class A
{
public :
class B ;
// etc.
} ;
class A::B
{
public :
// etc.
} ;
それで:
- 特権アクセス: A :: Bは、カプセル化を弱めるAのすべてのメンバー(メソッド、変数、シンボルなど)への特権アクセスを持っています。
- Aのスコープはシンボルルックアップの候補です: Bの内側からのコードは、Aからのすべてのシンボルをシンボルルックアップの可能な候補として見るため、コードを混乱させる可能性があります
- 前方宣言: Aの完全な宣言を行わずにA::Bを前方宣言する方法はありません。
- 拡張性: Aの所有者でない限り、別のクラスA::Cを追加することはできません。
- コードの冗長性:クラスをクラスに入れると、ヘッダーが大きくなるだけです。これを複数の宣言に分割することはできますが、名前空間のようなエイリアス、インポート、または使用法を使用する方法はありません。
結論として、例外がない限り(たとえば、ネストされたクラスはネストされたクラスの親密な部分です...そしてそれでも...)、欠陥が認識された利点の大きさよりも重要であるため、通常のコードではネストされたクラスには意味がありません。
さらに、C++名前空間を使用せずに名前空間をシミュレートする不器用な試みのようににおいがします。
プロ側では、このコードを分離し、プライベートの場合は使用できないようにしますが、「外部」クラスからは...
ネストされた列挙型
長所:すべて。
短所:何もありません。
事実、列挙型アイテムはグローバルスコープを汚染します。
// collision
enum Value { empty = 7, undefined, defined } ;
enum Glass { empty = 42, half, full } ;
// empty is from Value or Glass?
各列挙型を異なる名前空間/クラスに配置することで、この衝突を回避できます。
namespace Value { enum type { empty = 7, undefined, defined } ; }
namespace Glass { enum type { empty = 42, half, full } ; }
// Value::type e = Value::empty ;
// Glass::type f = Glass::empty ;
C++0xがクラス列挙型を定義したことに注意してください。
enum class Value { empty, undefined, defined } ;
enum class Glass { empty, half, full } ;
// Value e = Value::empty ;
// Glass f = Glass::empty ;
まさにこの種の問題のために。