2010-04-16 116 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想做的事,這並不什麼......