1

メンバー変数として特定の型を持つ抽象クラスを必要とするインターフェイスを指定したいと考えています。

ここで状況を再現してみます。

class Blob {
  int data[32];
};
class Worker {
  string name;
  abstract void workOn(Blob&) = 0;
}

class Abstract {
  vector<shared_ptr<W>> workerList;
  Blob allTheStuff;
  abstract void somethingElse() = 0;
  void doAllTheWork() {
    for (w : workerList) {
      w->workOn(allTheStuff);
    }
  }
};

class B_Blob : public Blob {
  int moreData[4096];
};

class BulbasaurTrainingCamp : public Abstract {
  B_Blob allTheStuff;
  void somethingElse() {} // implemented
  // this class will accept Bulbasaurs into workerList
};

class Bulbasaur : Worker {
  Bulbasaur(): name("Fushigidane") {}
  void workOn(Blob& b) {
    // bulbasaurs cover *all* their workspace with crap
    for (int i=0; i<sizeof(b.data[0])/sizeof(b.data); ++i) {
      b.data[i] = *((int*)&("crap"));
    }
    for (i=0; i<sizeof(b.moreData[0])/sizeof(b.moreData); ++i) {
      b.moreData[i] = *((int*)&("crap"));
    }
}

ここで、抽象basクラスにはBlobがありますが、のインスタンスにBulbasaurTrainingCampは派生がありますB_Blob。同じ名前を付けたので、コンパイラはそれを受け入れているようです。

これに名前はありますか?私が知りたいのは、これを行うときの動作です。を でオーバーライドしBlobましたB_Blobか?

の中にアクセスできない基本Blobインスタンスがぶら下がっているかどうかについては、基本的にわかりませんBulbasaurTrainingCamp。私の期待は、それぞれBulbasaurが. 私は、C++ が賢明に見えることを実際に行うことを望んでいます。それは、「コンパイルされたので、私は幸せだと思いますが、私はそれがやるべきだと思っていることをまだ完全には確信していません」というケースです.crapB_Blob

4

3 に答える 3

1
#include<iostream>
#include<vector>
using namespace std;

int main()
{
    class base
    {
    public: 
        int sameName;
        base(int x):sameName(x){}
    };
    class derived : public base
    {
    public:
        int diffName;
        int sameName;
        derived(int x,int i,int j):base(x),diffName(i),sameName(j){}

    };
    derived example(1,2,3);
    cout<<example.sameName<<endl;
    cout<<example.diffName<<endl;
    cout<<example.base::sameName<<endl;
}

結果は 3 2 1 です。この例がお役に立てば幸いです。

于 2013-08-26T04:31:28.540 に答える
0

基本クラスは、抽象クラスであっても、派生クラス内に完全に含まれます。新しいallTheStuff名前は古い名前を隠しますが、その包含を抑制しません。基本クラス バージョンには、引き続き を使用してアクセスできますAbstract::allTheStuff。さらに悪いことに、サブクラスに同じ名前のメンバー変数があることを認識できないため、関数doAllTheWorkは基本クラスにアクセスすることになります。allTheStuff

この種の動作が必要な場合は、適切なオプションがいくつかあります。

  1. 基本クラスに意味のあるコードやデータを入れないでください。純粋なインターフェースのままにします。これにより、コードが重複する可能性があります (ただし、新しい基本クラスまたは共有ヘルパー関数に分解できる場合があります)。
  2. として動的にサイズ変更可能なコンテナー タイプを使用してBlob、コンストラクターで動的に増減するスペースを要求できるようにします。
  3. 使用するを返す仮想関数を使用してBlob、別の継承階層を作成します (たとえばB_Blob、異なる量のスペースが割り当てられS_Blobた抽象から継承します) 。BlobAbstractBlob
于 2013-08-26T04:20:29.300 に答える
0

このコードは C++ を使用してコンパイルされると想定しているようです。確かにそうではありません。さまざまな C++/CLI 固有のパッチを適用した後でも、 a にBlobは呼び出されるデータ メンバーがなく、moreData(C++ を使用して) データ メンバーを取得する唯一の方法は、適切なキャストを使用することです。

オブジェクトには と呼ばれる 2 つのBulbasaurTrainingCampメンバがありallTheStuff、1 つは typeBlobで、もう 1 つは typeB_Blobです。どちらを取得するかは、対象のタイプ (すべてのメンバーが非公開であるため、何も取得できませんが、その詳細は無視しましょう) および/または使用する資格によって異なります。

BulbasaurTrainignCamp btc;
B_Blob&               b_blob = bts.allTheStuff;
Blob&                 blob1  = bts.Abstract::allTheStuff;

Abstract& abstract;
Blob&     blob2 = abstract.allTheStuff;

つまり、 a のように見えるものを使用する場合、と オブジェクトのBulbasaurTrainingCamp両方にアクセスできますが、 sメンバーにアクセスするには修飾を使用する必要があります。を使用する場合、 sオブジェクトにのみアクセスできます。BlobB_BlobAbstractallTheStuffAbstractAbstractBlob

于 2013-08-26T04:25:33.370 に答える