基类中的抽象基成员变量

时间:2013-08-26 04:09:13

标签: c++ c++11

我想指定一个接口,它要求抽象类将某种类型作为成员变量。

我会尝试复制这里的情况:

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"));
    }
}

此处,抽象基类具有Blob,但BulbasaurTrainingCamp的实例具有派生B_Blob。看来,既然我给了它相同的名字,编译器接受它。

这有名字吗?我想知道的是当我这样做时的行为。我是否已使用Blob覆盖B_Blob

我基本上不确定Blob内是否存在无法访问的基本BulbasaurTrainingCamp实例。我的期望是每个Bulbasaur将在crap的两个成员变量中写入16512(不是16384)字节B_Blob。我希望C ++实际上会做出看似合理的事情。这是一个例子,“它编译,所以我认为我应该感到高兴,但我仍然不能完全确定它正在做我认为它应该做的事情。”

3 个答案:

答案 0 :(得分: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。 我希望这个例子可能会有所帮助。

答案 1 :(得分:0)

基类,即使是抽象基类,也将完整地包含在任何派生类中。新的allTheStuff名称隐藏旧名称,但不会抑制其包含;仍然可以使用Abstract::allTheStuff访问基类版本。更糟糕的是,函数doAllTheWork将最终访问基类allTheStuff,因为它不可能知道子类中有一个同名的成员变量。

如果你想要这种行为,你有一些不错的选择:

  1. 不要在基类中放置任何有意义的代码或数据;把它留作纯粹的界面。这可能会导致代码重复(但您可能会将其分解为新的基类或共享辅助函数)。
  2. 使用动态大小的容器类型作为Blob,这样您就可以在构造函数中动态请求更多或更少的空间。
  3. 使Blob成为一个单独的继承层次结构(例如B_BlobS_Blob继承自具有不同空间分配量的抽象Blob,并在{{中使用虚函数1}}返回要使用的Abstract

答案 2 :(得分:0)

您似乎以某种方式假设此代码使用C ++编译。当然不会。即使在修补了各种C ++ / CLI细节之后,仍然认为Blob没有名为moreData的数据成员,而获取它的唯一方法(使用C ++)是使用合适的铸造。

BulbasaurTrainingCamp个对象将有两个名为allTheStuff的成员,一个类型为Blob,另一个类型为B_Blob。你得到哪一个取决于你所看到的类型(因为所有成员都是私人的,你不会得到任何,但让我们忽略那个细节)和/或你使用的资格:

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

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

也就是说,当使用看起来像BulbasaurTrainingCamp的内容时,您可以访问BlobB_Blob个对象,但是您需要使用限定条件来访问Abstract s allTheStuff成员。使用Abstract时,您只能访问AbstractBlob对象。