C ++:继承问题

时间:2010-04-16 12:06:13

标签: c++ inheritance

很难解释我正在尝试做什么,我会尝试:想象一个基础class A包含一些变量,以及一组派生自A的类,它们都实现了一些方法bool test()对从A继承的变量进行操作。

class A {
   protected:
   int somevar;
   // ...
};

class B : public A {
   public:
   bool test() {
      return (somevar == 42);
   }
};

class C : public A {
   public:
   bool test() {
      return (somevar > 23);
   }
};

// ... more classes deriving from A

现在我有一个class A的实例,我设置了somevar的值。

int main(int, char* []) {
    A a;
    a.somevar = 42;

现在,我需要某种容器,允许我遍历此容器的元素i,在i::test()的上下文中调用a ...即: / p>

    std::vector<...> vec;
    // push B and C into vec, this is pseudo-code
    vec.push_back(&B);
    vec.push_back(&C);

    bool ret = true;
    for(i = vec.begin(); i != vec.end(); ++i) {
       // call B::test(), C::test(), setting *this to a
       ret &= ( a .* (&(*i)::test) )();
    }
    return ret;
 }

我该怎么做?我尝试了两种方法:

  1. 强制从B :: *转换为A :: *,调整指针以在不同类型的对象上调用类型的方法(有效,但似乎很糟糕);
  2. 使用std :: bind +上面的解决方案,丑陋的黑客;
  3. 更改bool test()的签名,使其采用const A&类型的参数而不是从A继承,我不太喜欢这个解决方案,因为somevar必须是公共的。
  4. 修改

    解决方案(1)是:

    typedef bool (A::*)() mptr;
    std::vector<mptr> vec;
    vec.push_back(static_cast<mptr>(&T::test));
    
    std::vector<mptr>::iterator i;
    for(i = vec.begin(); i != vec.end(); ++i) {
       (a .* (*i))();
    }
    

    我不确定静态演员是否安全。

5 个答案:

答案 0 :(得分:5)

最干净的解决方案是你建议的最后一个,在test中使A成为(纯)虚拟函数:

virtual bool test(const A& value) = 0;

如果您因为somevar公开将其保密并仅提供公共获取功能而烦恼:

int getvar() const {return somevar;}

答案 1 :(得分:3)

您正尝试在B上调用CA方法。不要那样做。

您需要创建BC的实际实例,在vector<A*>中存储指向它们的指针,并在迭代期间调用定义的纯虚拟test()成员函数在A中(B::testC::test会覆盖)。

答案 2 :(得分:1)

添加“virtual bool test()= 0;”在A的定义中。

然后你可以在循环中执行以下操作:

ret = (ret && i->test());

BTW:“&amp; =”执行“按位和”,你可能想要逻辑和执行(&amp;&amp;)。

另外:你在向量中添加指针的B和C的实例都包含继承变量的副本,它们都是该变量的独立实例。

我认为你的代码如此处所示,存在很大缺陷。想一想你想要实际实现的目标是什么?

您是否希望对单个变量运行多种布尔测试,看看它是否与所有变量匹配? 或者每个约束是否真的要针对它自己的变量进行测试,你想获得所有那些独立测试的“布尔和”?

答案 3 :(得分:0)

这是迄今为止最干净的解决方案。它使用static

struct A {
   int somevar;
};

struct B {
   static bool test(const A& a) {
      return (a.somevar == 42);
   }
};

std::vector<bool (*)(const A&)> vec;

template<typename T>
void push(const T&) {
   vec.push_back(&T::test);
}

答案 4 :(得分:-1)

简单的解决方案:

将班级A更改为:

class A {
public:
    virtual bool test() const = 0;
protected:
    int somevar;
    // ...
};
  

现在,我需要某种容器,允许我迭代这个容器的元素i,在a。的上下文中调用i :: test()。

typedef std::vector<A*> ItemList;
ItemList items;
for(ItemList::const_iterator i = items.begin(); i != items.end(); ++i)
{
    if((*i)->test())
        ; // ???
}

所以我想知道OP想要做什么,这不是......