0

あるクラスまたは別のクラスからの汎用変数を作成したいと考えています。

このコード サンプルでは、​​クラス A またはクラス B のコードにアクセスできるように、var aa をジェネリックにする必要があります。

しかし、aa はグローバルでなければなりません。

私たちを手伝ってくれますか?

class MyClass
{
public:
    MyClass() {} //contructor padrão, não deve ser utilizado isoladamente

    static MyClass* getInstance()
    {
        static MyClass *instance = 0;
        if (!instance) instance = new MyClass();
            return instance;
    }
};

class A : public MyClass
{
public:
    int a() { return 1; }
};

class B : public MyClass
{
public:
    int b() { return 1; }
};

template <class TAIT> class AIT
{
public:
    static TAIT& Instance()
    {
        static TAIT instance;
        return instance;
    }
};

AIT aa;

void main()
{
    aa.Instance().a(); // or
    aa.Instance().b(); // aa could be class
                       // A or class B. So I could access
                       // function a or function b (not at same
                       // time, of course)

    return;
}
4

6 に答える 6

7

簡潔な答え:

C++ テンプレートは、実行時のジェネリック性ではなく、コンパイル時のジェネリック性を提供します。

テンプレート自体は、プログラム内には存在しません (つまり、具体的なバイナリ実行可能ファイルとして)。それらは、引数を明示的または暗黙的に指定してインスタンス化した場合にのみ、生成されたコードになります。

したがって、これは変数を宣言しません。

AIT aa;

これは変数を宣言します:

AIT<A> aa;

ランタイムの汎用性が必要な場合は、ランタイム ディスパッチ メカニズムを使用する必要があります。

  • スイッチケースを使って手動で行うか。
  • または、共通の基本クラス + いくつかの仮想メソッドの組み込み継承を使用することをお勧めします。
于 2009-06-26T14:20:49.473 に答える
2

私があなたを正しく理解していれば、aa正しく宣言するだけでよいと思います。設定は次のとおりです。

AIT<A> aa;
aa.Instance().a();

AIT<B> bb;
bb.Instance().b();

そうでない場合は、質問を編集して、何をしようとしているのかを明確にしてください。

于 2009-06-26T14:13:45.400 に答える
1

基本クラスで純粋仮想を宣言し、派生クラスでオーバーロードします。

class MyClass {
public:
   virtual int a() = 0;
};

class DerivedA : public MyClass {
public:
   virtual int a() { return 1; }
};

どちらの派生クラスにも同じ名前のメソッドがあり、オブジェクトの種類に応じて呼び出すメソッドが自動的に解決されます。作成するクラス インスタンスを認識できるように、GetInstance() メソッドの作成部分を書き直す必要があります。

于 2009-06-26T14:13:40.003 に答える
0

getInstance メソッド以外からコンストラクターを呼び出したくない場合は、プライベートにすることができます。例えば

class MyClass
{
private:
    MyClass() {} //contructor padrão, não deve ser utilizado isoladamente
public:
    static MyClass* getInstance()
    {
        static MyClass *instance = 0;
        if (!instance) instance = new MyClass();
            return instance;
    }
};

MyClass* a = new MyClass();

コンストラクターがプライベートであるため、コンパイル エラーが発生します

于 2009-06-26T14:36:01.020 に答える
0

これはこの問題の良い解決策ですか?

class MyClass { public: MyClass() {} //contructor padrão, não deve ser utilizado isoladamente virtual int a() = 0; 仮想 int b() = 0;

  int c()         {           return b();         }

   static MyClass* getInstance()
   {
      static MyClass *instance = 0; //          if (!instance) instance

= 新しい MyClass(); インスタンスを返します。} };

クラス A : public MyClass { public: int a() { return 1; } int b() { 1 を返します。} int d() { 1 を返します。} };

クラス B : public MyClass { public: int a() { return 1; } int b() { 1 を返します。} int e() { 1 を返します。} };

クラス C : public A、public B { public: A ca; Bcb;

enum TIPO { A, B }; ティポ ティポ;

C(TIPO ティポ) { ティポ = ティポ; }

int a() { switch(Tipo) { ケース A: return ca.a(); 壊す; ケース B: cb.b() を返します。壊す; デフォルト: ブレーク; } }

};

void main() { //MyClass* A = MyClass::getInstance(); //MyClass* B = MyClass::getInstance();

Cc(C::B); ca();
// aa.Instance().a(); // aa.Instance().b();

戻る; }

于 2009-06-29T15:16:19.850 に答える
0

確かに厄介ですが、おそらくここでの解決策は、void ポインターを使用することです。C および C++ では、void* として宣言されたポインターは型を持たないように定義されます。このポインターを渡してから、任意のデータ型のポインターにキャストできます。変数が実際に正しい型であることを注意深く確認することは明らかに重要ですが、戻り値の型がわからないインターフェイスを設計している場合は、これが役立ちます。インターフェイス クラスがどのように見えるかの例を次に示します。

class InterfaceClass {
  public:
     virtual void* someInterface() = 0;
}

次に、インターフェイスを実装し、必要な興味深いことを行う別のクラスを作成できます。

class DerivedClass: public InterfaceClass {
  public:
     virtual void* someInterface() {
        //do some stuff
        return (void*) somePointer;

}

コードが何をすべきかを理解している限り、どんなタイプのポインタでも返すことができます。Google で void ポインターを検索すると、さらに多くの情報が得られます。気をつけて。

于 2009-07-02T06:37:00.047 に答える