2010-04-16 256 views
3

这是相当难以解释什么,我试图做的,我会尝试:想象一下,一个基地class A其中包含了一些变量,以及一组从A派生类,所有实现一些方法bool test()经营关于从A继承的变量。C++:继承问题

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,在a情况下调用i::test() ...那就是:

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必须是公共的。

编辑:

解决方案(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))(); 
} 

我不知道静态浇铸是安全的。

+1

覆盖的子虚拟方法中操作父状态粗劣:有什么问题,你实际上* *尝试在这里解决?关于你的关于使somevar公开的评论的附注,它已经被保护了,它只是一个稍微受限制的公共形式,因为它已经将你的班级的内部状态暴露给任意修改。 – 2010-04-16 14:36:05

+0

通常当你遇到这样的问题时,你可能会以错误的方式回答这个问题。这并不能帮助你找出正确的方法,但至少你有线索开始寻找它。 – Jay 2010-04-16 15:46:37

回答

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

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

然后,你可以做你的循环如下:

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

BTW:“& =”做了“按位与”和你可能想的逻辑和执行( & &)。

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

我认为你的代码,如下所示,是相当有缺陷的。想更多关于你想要实现的目标?

您是否想对单个变量运行多重布尔测试并查看它是否与所有变量匹配? 或者是每个禁忌真的要针对自己的变量进行测试,并且您想获得所有这些独立测试的“布尔值”?

+1

这不是OP所感兴趣的内容。'test()'不应该在'i'上调用,而是在对象'a'上调用。 – 2010-04-16 12:12:58

+0

我明白你的意思,但那会是#EPIC FAIL。 即使这样,修正它的唯一方法是让A具有虚拟成员函数test()。 – haavee 2010-04-16 12:35:17

3

您正试图在A上调用BC方法。不要这样做。

您需要创建的BC实际情况,将指针存储到他们在一个vector<A*>和,迭代过程中,请致电A(其中B::testC::test将覆盖)定义的纯虚test()成员函数。

5

的干净的解决方案是最后一个你的建议,让test一个(纯)虚函数在A

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

如果你有做somevar公共保持私营和供应只有一个公共的get困扰功能:

int getvar() const {return somevar;} 
+1

鉴于您现在将“const A&”传递给test(),不需要将test()作为成员函数,您可以返回使用常规函数指针。让阅读更轻松:) – haavee 2010-04-16 12:45:42

-1

简单的解决方案:

更改类A到:

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

现在,我需要某种容器,让我来遍历元素我在这个容器的上下文中调用i :: test()。

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

所以我想知道OP想做的事,这并不什么......