2011-05-09 7 views
5

私は、より高水準のファイルクラスで使用される簡単で低レベルのコンテナクラスを持っています。基本的に、ファイルクラスはコンテナを使用して、最終バージョンを実際のファイルに保存する前にローカルに変更を保存します。したがって、いくつかのメソッドは、コンテナクラスからファイルクラスに直接移ります。 (たとえば、Resize()メンバーからメソッドをコピーする

私は、ファイルクラスのメソッドを定義して、コンテナクラスのバリアントを呼び出すようにしています。例:

void FileClass::Foo() 
{ 
    ContainerMember.Foo(); 
} 

これは厄介なものになります。これを行うより良い方法はありますか?これは非常に迷惑であるよう

class MyContainer 
{ 
    // ... 

    public: 

    void Foo() 
    { 
     // This function directly handles the object's 
     // member variables. 
    } 
} 

class MyClass 
{ 
    MyContainer Member; 

    public: 

    void Foo() 
    { 
     Member.Foo(); 

     // This seems to be pointless re-implementation, and it's 
     // inconvenient to keep MyContainer's methods and MyClass's 
     // wrappers for those methods synchronized. 
    } 
} 
+0

私はここに組成を見て、継承していません。何か不足していますか? –

+0

@Dougコンテナクラスから継承する方法があるかどうか、または私の例では、「MyContainer」がいくつかの方法であるかどうかを確認しています。 (もしあればもっと良い解決法があります)私は質問をより明確に編集します。 – Maxpm

+1

その場合は、MyContainerを、必要なメソッド(およびそれから継承する)と、残りのMyContainerメソッドを別のクラスに持つクラスに分割する必要があります。 – dlev

答えて

7

なぜ、MyContainerからプライベートに継承して、ちょうどusing宣言で転送したい機能を公開しないのですか?それが「MyContainerの面でMyClassを実装する。今

class MyContainer 
{ 
public: 
    void Foo() 
    { 
     // This function directly handles the object's 
     // member variables. 
    } 

    void Bar(){ 
     // ... 
    } 
} 

class MyClass : private MyContainer 
{ 
public: 
    using MyContainer::Foo; 

    // would hide MyContainer::Bar 
    void Bar(){ 
     // ... 
     MyContainer::Bar(); 
     // ... 
    } 
} 

『と呼ばれているBarMyClassの内側にのみアクセス可能である一方、』外は、直接Fooを呼び出すことができます。あなたは今で機能させる場合同じ名前が、それは基本機能を隠し、あなたはそのような基本機能をラップすることができます。もちろん、あなたは今、完全に基底関数の呼び出しを修飾する必要があるか、無限再帰に行きます。


さらに、私はこれはまれな場所の一つであるよりも、F君は、MyClassの(非polymorphical)サブクラス化を許可する保護された継承は、実際には有用です:

class MyClass : protected MyContainer{ 
    // all stays the same, subclasses are also allowed to call the MyContainer functions 
}; 

非polymorphicalあなたMyClassは何の仮想デストラクタを持っていない場合。

1

はい、プロキシクラスを維持する:ここで

は簡略化した例です。あなたのIDEには、少し簡単にするためのツールがあるかもしれません。または、IDEアドオンをダウンロードできるかもしれません。

しかし、何十もの機能やオーバーライドとテンプレートをサポートする必要がない限り、通常はそれほど難しくありません。それはいいと対称的だ

void Foo()  { return Member.Foo(); } 
int Bar(int x) { return Member.Bar(x); } 

私は通常のようにそれらを書きます。 C++では、void関数のvoid値を返すことができるため、テンプレートがうまく機能するためです。しかし、同じことを使って他のコードをもっときれいにすることができます。

1

それはdelegation inheritanceだから、私はC++がそれを手助けするメカニズムを提供しているのか分かりません。

1

MyClassとMyContainerの間の関係(a)または継承(a)の関係を考えてみましょう。

このようなコードをもう作成したくない場合は、実装の継承(基本/抽象基本クラスとしてのMyContainer)にかなり制限されています。しかし、実際にはアプリケーションでこれが意味をなさないことを確認しなければなりません。また、実装のために継承されるわけではありません(実装の継承が悪い)。

疑問がある場合は、おそらく問題ありません。

編集:私はJava/C#で思考するのに慣れており、C++にはより大きな継承の柔軟性があることを見落としています。それはちょうどこの場合に素晴らしい解決策のように感じる。

0

大量のコードを書く必要があるこの機能は、実際には必要な機能です。 C++は冗長な言語なので、C++でコードを書くことを避けようとすると、デザインは決してうまくいかないでしょう。

しかし、この質問の本当の問題は、クラスには何の振舞いもないことです。それは何もしない単なるラッパーです。すべてのクラスは、単にデータを渡す以外の何かをする必要があります。

重要なことは、すべてのクラスに正しいインターフェイスがあることです。この要件により、転送機能を記述する必要があります。各メンバー機能の主な目的は、すべてデータメンバーに必要な作業を配布することです。データメンバーが1つしかなく、クラスが何をすべきかをまだ決めていない場合は、関数を転送するだけです。一度メンバーオブジェクトを追加し、クラスが何をすべきかを決定すると、転送関数はもっと妥当なものに変わります。

これを助ける1つのことは、クラスを小さく保つことです。インターフェイスが小さい場合、各プロキシクラスは小さなインターフェイスしか持たず、インターフェイスはあまり頻繁に変更されません。

+0

クラスは*何かをします*。私の例は、質問のために単純化されました。 – Maxpm

関連する問題