2011-10-21 10 views
4

私はオブジェクトとobject_managerという2つのクラスを作成したいが、どのように見なければならないか混乱している。私はそれが2つのヘッダーがお互いを含むことが禁じられていると聞いたことがあります。もし私のコードの依存関係が円であるならば、それは悪いコードデザインであり、通常階層構造のようにすべきです(町→家 - 町の存在について)。C++オブジェクト階層の依存関係コードデザイン

しかし、ここではすべてのオブジェクトを把握しているオブジェクトマネージャがあり、オブジェクトには新しいオブジェクトを作成するオプションが必要ですが、object_managerを呼び出すとオブジェクトの存在を知る必要があります。一つのプロセスは、OSのシステムコールを呼び出すことによって、新しいプロセスを作成したいので、OSやプロセスがお互いを知っているみたいだ悪い構造の円..

..

です正しいコードデザインでこれを実装する方法がありますか、時にはそれが悪いはずですか?

私は、オブジェクトが "システムコール"をすべて格納する特別な場所を持つべきだと思っていました。そして、object_managerはそれを時々チェックしますが、もっと良い方法があります。

+5

+1 "アナーキー構造" – AJG85

答えて

1

利用前方宣言:

class ObjectManager; 

class Object 
{ 
private: 
    ObjectManager* m_objManager; 
    .... 
public: 
    .... 
}; 

.Cppファイルには、ObjectManager.hを含めることができます。 ObjectManagerの代わりに、IObjectManagerの実装のための抽象化を提供するインターフェイスを作成します。

幸運:)。

0

CPPファイルには、コンパイルの問題(デザインの観点からは正しいかどうかは関係ありませんが、yurの場合は問題ありません)を行うことなく、お互いのヘッダーを含めることができます。これはヘッダファイル、「オブジェクトマネージャ」「オブジェクトマネージャ」クラスはオブジェクト」と連携する必要があるため、ヘッダが最も可能性が高い「オブジェクト」ヘッダが含まれますについて

など、彼らは互いのメソッドを呼び出すことができることを意味します"クラスインスタンス。 「オブジェクト」ヘッダファイルが「オブジェクトマネージャ」クラスについて知る必要がある場合、「オブジェクトマネージャ」の前方宣言を「オブジェクト」ヘッダファイルに配置する。こうすることで、円のインクルード依存関係を作成せずに、 "オブジェクト"ヘッダーファイルの "オブジェクトマネージャ"へのポインタと参照を使用することができます。ヘッダ間の結合を削除する

0

いくつかの一般的な推奨事項は、次のとおりです。フォワード

何をでき宣言します。 Aクラスでは、参照やポインタを渡すだけで他のクラス(X、Y、..)を使用することがあります。したがって、A.hでは、完全な型を知る必要があるコンパイラなしで、これらのX、Yの戻り値または引数の型を使用するメソッドを宣言することができます。


:それはのようなものをやっている時々、(仮想または抽象クラスを使用せずに)インタフェースから実装を分離するための最良の方法をイディオム A.hX.hまたは Y.h

使用PIMPLを含める必要がないことを意味します

がfoo.h

class Foo { 
struct Impl; 
Impl* m_impl; 

public: 
Foo(); 
void SomeMethod(); 

} 

フー。 cpp

#include "X.h" 
struct Foo::Impl { 
/* actual implementation */ 
...}; 

Foo::Foo() : m_impl(new Foo::Impl()) {}; 

void Foo::SomeMethod() { 
m_impl->SomeMethod(); 
} 
0

クラスが互いに知り合う必要があるケースはたくさんあります。これに関する唯一の問題は、お互いを部分的に知っていなければならないことです。問題が一般的に解決される方法は、forward declarationsを使用しています。唯一の粘着性の問題は、クラスBのみポインタまたはクラスBへの参照の型を持つメンバーを宣言することはできませんクラスAである

class B; 
class A 
{ 
    B* oB; 

}; 

class B 
{ 
    A oA; 
}: 
1

実際には、2つを実装することは可能です。それは本当に悪いことではありません。ここにいくつかの部分的なコードがあります。

あなたがObjectManagerのヘッダのObjectManager

#include <myobject> 
#include <myobjectmanager> 

MyObjectManager::manageMyObject(MyObject &o) { 
    list += o; /* etc. */ 
} 

#ifndef _MYOBJECT_MANAGER 
#define _MYOBJECT_MANAGER 

class MyObject; // forward declaration 

class MyObjectManager { 
     private: 
       List list[]; 
     public: 
       registerObject(MyObject &o); 
}; 

#endif 

実装のための今すぐヘッダファイル

myobject.h

#ifndef _MYOBJECT 
#define _MYOBJECT 
// Declare the Object Manager class in it. 

class MyObjectManager; // forward declaration 

class MyObject { 
     MyObjectManager manager; 
     registerSelf(MyObjectManager &m); 
} 

#endif _MYOBJECT 

を持っているとしましょうあなたが記述しているどのようなオブジェクト

​​
0

の実装は、が別のオブジェクトの内側にのみ存在できることを目的としています。あなたはまだ、オブジェクトとobject_managerのための2つのcppのファイルを持つことができることに留意してください

class object_manager { 
    public: 
    class object { // object_manager::object. public allows it to be used outside of manager 
    public: 
    void foo() { 
     object* t = construct(); // can call object_manager methods 
    } 
    }; 

    private: 
    object my_objects[5]; // can create objects 
    static object* construct() { return NULL; } 
}; 

:これを実装する

良い方法は、ネストされたクラスです。

関連する問題