2010-11-21 13 views
0

私はC++を学んでいますが、問題が残っています。私はベースクラス内の特定のサブクラスを使用する方法が必要です。それは意味をなさないか、間違ったアプローチを使用していますか? SelectBrandはサブクラスを選択する必要があります。どうすればいいですか?ここに私の簡略化されたクラス以下ベースクラスからサブクラスを選択できます...可能ですか?


----- 
class Protocol { 

public: 

    Protocol() {}; 
    ~Protocol() {}; 
    int openPort(); 
    int readPort(char *buffer); 

..... 

private: 

     Protocol (const Protocol&); 
}; 

int Protocol::openPort() {......}; 

int Protocol::readPort() {.........}; 

/***********************************************************************************/ 

class Device{ 

public: 

     Device(Protocol& port):_protocol(port){} 
     ~Device(); 
     virtual int getEvent(char *buffer) { return -1; } 
     int Device::selectBrand(); 

     .............. 

protected: 

     Protocol& _protocol; 

private: 

     int brand; 
     Device(const Device&orig); 
}; 

Device::~Device() {} 

int Device::selectBrand() { 

     ...... 

     switch (X) 

      case 1: 

        "use subclass Brand_B" 

      case 2: 

        "use subclass Brand_B" 

     ....... 

} 

/***********************************************************************************/ 

class Brand_A:public Device { 

public: 

     Brand_A(Protocol& port); 
     ~Brand_A(); 
     int getEvent(void *rawData); 

private: 

     Brand_A(const Brand_A&); 
}; 

Brand_A::Brand_A(Protocol& port):Device(port) {} 

Brand_A::~Brand_A() {} 

int Brand_A::getEvent(void *rawData) { 


      .... readPort(......); 

} 

/***********************************************************************************/ 

class Brand_B:public Device { 

public: 

     Brand_B(Protocol& port); 
     ~Brand_B(); 
     int getEvent(void *rawData); 

private: 

     Brand_B(const Brand_B&); 

}; 

Brand_B::Brand_B(Protocol& port):Device(port) {} 

Brand_B::~Brand_B() {} 

int Brand_B::getEvent(void *rawData) { 


      .... readPort(......); 

} 

/* main **********************************************************/ 

int main(int argc, char **argv) { 

     Device *mydev; 

     char *buffer; 

    .............. 

    mydev->selectBrand(); 

    .......... 

    mydev->getEvent(buffer); 

    ........... 

} 
+0

あなたの例では、あまりにも多くの '....'セクションがあります。 'selectBrand'が実際に何をするのかは不明です:' X'は何ですか?そして 'use subclass 'はどういう意味ですか? – casablanca

+0

サブクラスを取得するためにオブジェクトをダウンキャストしようとしている場合は、あなたのアプローチに欠陥があります。私は非常に多くのコードを提供することは混乱していると思います。主要なクラス、メソッド、そして使い方についてはどうですか? – belwood

+0

'〜Device()'はおそらく 'virtual'でしょう。 – fredoverflow

答えて

2

これは良いアイデアではありません。

は、一般的な答えはdynamic_castですが、基本クラスから下位の特定の動作を呼び出すと、通常は悪いデザインのサインです。

あなたはクラス階層を反転し、テンプレートを使用して試すことができます。

0

あなたはC++があなたのためにそれを行うだろうとき多型のようなものを実装しようとするかもしれないように見えます。基本クラスに仮想メソッドを定義し、それらをサブクラスでオーバーライドする場合は、ポインタまたはそれらの基本タイプへの参照でこれらのメソッドを呼び出すと、サブクラスの実装が呼び出されます。例えば

class BaseClass 
{ 
    virtual void DoSomething() 
    { 
     printf("base"); 
    } 

}; 

class SubClass : public BaseClass 
{ 
    void DoSomething() 
    { 
     printf("sub"); 
    } 
}; 

int main() 
{ 
    BaseClass *myBase = new SubClass(); 
    myBase->DoSomething(); // should print "sub" to stdout 

    return 0; 
} 

あなたが派生どのタイプ(サブクラスのタイプ)を使用すると、インスタンスが派生型の追加機能を持つようにあなたがそれを作成するときに使用したいを知っている必要があります。そうしないと、基本クラスの機能がすべて得られます。基本クラス以外のもの(または、基底クラスが何かを継承する場合は継承階層の上にあるもの)として扱うことはできません。

あなたも、彼らは実際には異なる何もしていない場合は、別のインスタンスを区別するためにメンバーを使用することができます。コードサンプルから、あなたがしたいことを正確に伝えるのは難しいです。たぶん、達成しようとしている方法よりも、達成しようとしているもののより具体的な例が役立つでしょう。

+0

私の問題は主に私が使用する必要があるサブクラスがわからないことです。これはselectBrandという基本クラスの関数への要求です。いくつかのチェックに基づいて、コードはサブクラスbarnd_aまたはbrand_bを使用します。 – Luke

+0

BaseClass * myBase = new SubClass();完璧になるだろう....しかし、私は選択するより多くのサブクラスを持っている場合は? – Luke

+0

あなたの2番目の投稿を読んだ後、私は問題が少し良くなると思っています。どのクラスを使用しているかを知らずに、基本クラスで宣言されているメソッドの異なる実装を使用しようとするなら、おそらく抽象的なファクトリパターンが必要です。何かのように:デバイス*デバイス=デバイス:: CreateDevice();ここで、Deviceはデバイスの一般的なメソッドを宣言するインタフェースクラスであり、返されるインスタンスはCreateDevice()によって決定される特定のデバイスです。 – ajmccluskey

0

お願いします。問題を再調整してください。私は1つのbaseClassといくつかのサブクラスを持っています。 Brand_Aは.... Brand_N

今、メインでは()私は、私が使用するどのサブクラス事前に知りません。この選択はselectBrandと呼ばれるbaseClassの関数に要求されます。私が必要とするのは、内部条件に基づいて適切なサブクラスを選択して使用する仕組みです。私は選択されたサブクラスmain()に偽装したい。これを得る方法?

1

私は、私が上で作ったコメントを肉食しなければならないと思った。まず、abstract factory patternの詳細については、Wikipediaのページをご覧ください。基本的には、インタフェースのさまざまな実装にアクセスし、実行時に決定された実装を使用することができます。しかし、インターフェイスの実装を返すファクトリメソッドで決定されているので、どのインプリメンテーションが得られているのかまだ分かりません。その結果、特定の実装ではなく、インターフェイス内のメンバーのみを使用することができます。上記のあなたのクラスを使用する例は次のようなものになるだろう:私はこのコードを実装し、テスト

class Device 
{ 
    virtual int getEvent(void *rawData) = 0; 
} 

class BrandA : public Device 
{ 
    // define constructors/destructors etc. 

    int getEvent(void *rawData) 
    { 
     // BrandA's implementation for getEvent 
    } 
} 

class BrandB : public Device 
{ 
    // define constructors/destructors etc. 

    int getEvent(void *rawData) 
    { 
     // BrandB's implementation for getEvent 
    } 
} 

class DeviceFactory 
{ 
    static Device *CreateDevice(/*any parameters for determining the device?*/) 
    { 
     // You probably don't want to randomly determine which implementation you use... 
     if ((rand() % 2) == 0) 
     { 
      return new BrandA(); 
     } 
     else 
     { 
      return new BrandB(); 
     } 
    } 
} 

int main() 
{ 
    // CreateDevice will decide which type of device we use, however we can only 
    // explicitly reference the members of the base class (Device). 
    Device *myDevice = DeviceFactory::CreateDevice(); 

    myDevice->getEvent(); 

    return 0; 
} 
+0

はい - 質問の要件を理解していると仮定すると、これは間違いなく正しい方法です。特に、基底クラスは継承しているクラスについては何も知らず、常に正しいことを示す記号です:-) – psmears

0

。それはうまく動作します。それは良いデザインですか、それとも良くできますか?

class BehaviorBase 
{ 
public: 
    virtual ~BehaviorBase() {} 
    virtual void DoSomethingOn(Object* obj) {} 
}; 

class Object 
{ 
public: 
    BehaviorBase* behavior; 
    void DoSomething(); 
    void ChangeBehavior(int param); 
    ~Object(); 
} 

class BehaviorA: public BehaviorBase 
{ 
    void DoSomethingOn(Object* obj) 
    { 
    printf("Behavior A\n"); 
    } 
}; 

class BehaviorB: public BehaviorBase 
{ 
    string other_data; 
    void DoSomethingOn(Object* obj) 
    { 
    printf("Behavior B\n"); 
    } 
}; 

void Object::DoSomething() 
{ 
    behavior->DoSomethingOn(this); 
} 

Object::~Object() 
{ 
    delete behavior; 
} 

void Object::ChangeBehavior(int param) 
{ 
    delete behavior; 
    switch(param) 
    { 
     case 1: behavior = new BehaviorA; break; 
     case 2: behavior = new BehaviorB; break; 
    } 
}  

int main(int argc, char **argv) { 
    int param=1; 
    Object *obj; 
    obj= new Object; 

    obj->ChangeBehavior(param); 
    obj->DoSomething();  
    delete obj; 
    return(0); 
} 
関連する問題