-2
#define classAnum 2;
#define classBnum 3;

class Base
{
  virtual int open()=0;
  virtual int close()=0;
}
class A:public Base
{
 virtual int open();
 virtual int close();
};

class B:public Base
{
 virtual int open();
 virtual int close();
}

int main()
{
    A classA[classAnum];
    B classB[classBnum];

openAnyClass(1);
CloseAnyClass(2);   
}

このような機能を実現したい。

openAnyClass(1);
CloseAnyClass(2); 

これらの2つの関数は、クラスAおよびBのいずれかからopen()およびclose()を呼び出すことができる必要があります。

openAnyClass(1)は、classAまたはclassBのいずれかの配列内の最初のオブジェクトのopen()関数を呼び出します。

open()->は、クラスAとクラスBで異なる実装になります。クラスAのopen()は、複数のクライアントと最大で呼び出される場合があります。番号。クライアントの数は#定義されています。

一度に、classAまたはclassBのいずれかから1つのopen()のみが呼び出されます。同じコードのコピーをいくつか持ちたくありません。

1つの関数だけで、クラスAとクライアントのいずれかのopen()を呼び出します。

たとえば、次のステートメントで、client1のクラスAのopen()を呼び出します。openAnyClass(int)のパラメーターは、クライアントIDを示します。これはまた意味することができますclassB[1].open();

'openAnyClass(1) = classA[1].open();'

これを行うための最良の方法は何ですか?

4

3 に答える 3

1

これが、派生元のコマンド ベース クラスを持つ理由です。そうすれば、クラスへのポインターまたは参照を取得し、仮想関数を介して派生クラスで open/close メソッドを呼び出すことができます。

もしあなたが持っていたら

Base *generic_class_pointer = new class A();

generic_class_pointer->open();

generic_class_pointer->open() は、クラス A で定義されたコードを呼び出します。

オブジェクトを格納する 2 つの配列 (クラス A 用とクラス B 用) でやろうとしていることは必須ではありません。Base 型のクラスを参照する単一の配列を使用し、これを介してアクセスできます。

元のコードは実際には良い方法ではありません。リストを介してこれを行う方が良いです (例: stl::vector )。

Base* class_storage[StorageSize];

int openAnyClass(int id)
{
    if (id < 0 || id >= StorageSize || class_storage[id] == 0)
        return 0; // or other error indication
    else
        return class_storage[id]->open();
}
int CloseAnyClass(int id)
{
    if (id < 0 || id >= StorageSize || class_storage[id] == 0)
        return 0; // or other error indication
    else
        return class_storage[id]->close();
}


int main()
{
    memset(class_storage,0,sizeof(class_storage));

    class_storage[1] = new A();
    class_storage[2] = new B();

    openAnyClass(1);
    CloseAnyClass(2);   
}

上記のコードは完全な解決策ではありません。たとえば、派生クラスがクリーンアップを行う必要がある場合に備えて、元のコードには常に使用することをお勧めする仮想デストラクタがありません。

また、私のサンプルでは、​​class_storage に割り当てられたオブジェクトの削除が解放されません。それらは終了時に解放されるため、グローバル レベルでは問題になりませんが、ほとんどの場合、取得したすべてのものを管理する必要がありnew()ます。そうしないと、メモリ リークが発生します。

于 2012-07-09T10:26:56.017 に答える
0

したがって、classA は A の配列であり、classB についても同じです。openAnyClass(1) の呼び出しは、A のすべてのインスタンスで open() を呼び出すことを意味し、closeAnyClass() は、classB のすべてのインスタンスで close() を呼び出すことを意味します。もしそうなら、質問は非常に複雑に定式化されています

とにかく、それを行うためのすぐに使える既知の方法はありません。配列のすべての要素を繰り返し処理し、open() または close() を呼び出す必要があります。または、boost foreach http://www.boost.org/doc/libs/1_39_0/doc/html/foreach.htmlを使用する か、独自の foreach メソッドを実装することもできます

于 2012-07-09T10:27:13.137 に答える
0

あなたの質問を正しく理解できれば、純粋仮想関数のさまざまな実装を呼び出す必要があります。クラス A とクラス B の実装を提供したと仮定すると、ポリモーフィズムを利用して、A または B の代わりにベースへのポインター/参照から open()/close() を呼び出すことができるはずです。

A と B の 2 つの配列を作成する代わりに、ベース ポインターの配列を 1 つだけ作成できます。

例:

Base* base[basenum];

void openAnyClass( const int i )
{
   if( i < basenum && i >=0 && base[i] != NULL )
       base[i]->open();
}

int main(void)
{
   base[0] = new A();
   base[1] = new B();
   ...
   openAnyClass(1);
   closeAnyClass(2);

   for( int i = 0 ; i < basenum ; i++ )
      delete base[i];
}

補足として、次のような open 関数と close 関数を利用する方が良いと思います。

void openAnyClass( Base& base );
void closeAnyClass( Base& base );

グローバル変数を使用してオブジェクトを格納し、インデックスを渡すのではなく、オブジェクトのポインター/参照を関数に渡すと、関数は適切なメソッド (メソッド A または B) を呼び出します。

于 2012-07-09T10:32:30.053 に答える