2009-06-05 12 views
3

に子クラスの静的メソッドのオーバーロードを強制します。 2番目のクラスでLolz()メソッドを明示的に宣言するか、Produce<Child>()を使用するときにコンパイル時エラーがスローされるのでしょうか?は、私はこのような何かを持っているC++

それとも悪いのOOのデザインと私は全く別の何かをする必要がありますか?

EDIT:

私は基本的にやろうとしています何が、この作品のようなものを作ることです。

より一般
Manager manager; 

manager.RegisterProducer(&Woot::Produce, "Woot"); 
manager.RegisterProducer(&Goop::Produce, "Goop"); 

Object obj = manager.Produce("Woot"); 

か、知らない外部の抽象工場作成しているオブジェクトの型を変更することで、より多くのコードを記述することなく新しい型を追加することができます。

+0

状況について詳しく説明していただけますか?あなたのプログラミングのように、ある種の工場のものです。 – diapir

+1

マネージャのProduceメソッドが基本クラスへのポインタを返している場合、テンプレートを使用する際のポイントは何ですか? void RegisterProducer(Object *(* pfnProduce)()、const char * pName) –

答えて

6

回避するには2通りの方法があります。実際には、あなたが何を言いたいかによって異なります。

(1)BaseクラスのインタフェースとしてProduce()を作成する。

template <typename T> 
int Produce() 
{ 
    return T::Lolz(); 
} 
class Base 
{ 
    friend int Produce<Base>(); 

protected: 
    static int Lolz() 
    { 
     return 0; 
    } 
}; 

class Child : public Base 
{ 
public: 
    int nothing; 
}; 

int main(void) 
{ 
    Produce<Base>(); // Ok. 
    Produce<Child>(); // error :'Base::Lolz' : cannot access protected member declared in class 'Base' 
} 

(2)テンプレートの特殊化を使用します。

template <typename T> 
int Produce() 
{ 
    return T::Lolz(); 
} 
class Base 
{ 
public: 
    static int Lolz() 
    { 
     return 0; 
    } 
}; 

class Child : public Base 
{ 
public: 
    int nothing; 
}; 

template<> 
int Produce<Child>() 
{ 
    throw std::bad_exception("oops!"); 
    return 0; 
} 

int main(void) 
{ 
    Produce<Base>(); // Ok. 
    Produce<Child>(); // it will throw an exception! 
} 
+0

ありがとうございました!ナンバー1は私が探していたものとまったく同じものでした。 – GhassanPL

1

C++は仮想静的関数をサポートしていません。それをサポートするためにvtableがどのように見えなければならないか考えてみましょう。

2

サブクラス内の静的メソッドをオーバーライドする方法はありませんが、非表示にすることはできません。また、サブクラスに定義を提供させる抽象メソッドに類似したものもありません。異なるサブクラスで実際に異なる動作が必要な場合は、Lolz()をインスタンスメソッドにして、それを通常通りオーバーライドする必要があります。

私はあなたがここでデザイン問題に近づいていると考えています。オブジェクト指向設計のプリンシパルの1つは、置換主体です。基本的に、BがAのサブクラスであれば、Aを使用できる場所であればどこでもBを使うことが有効でなければならないと言います。

0

あなたの質問を理解する限り、親クラス。あなたは、派生クラスでこのような何かを行うことができます。


class Child : public Base 
{ 
public: 
    int nothing; 
private: 
    using Base::Lolz; 
}; 

今すぐ Child::Lolzはプライベートになります。 しかし、もちろん、デザインを修正する方がはるかに良いです。

関連する問題