2013-04-04 100 views
1

我有一個類,A,它需要靜態事件處理程序。我需要靜態事件處理程序,因爲中斷正在調用事件處理程序。帶繼承類的虛指針

class A { 
private: 
    static void (*fn1)(); 

public: 
    A(); 
    static void setFn1(void (*function)(void)); 
    static void onEvent(); 
}; 

A::A() { } 

void A::setFn1(void (*function)(void)) { 
    fn1 = function; 
} 

void A::onEvent() { 
    A::fn1(); 
} 

我想繼承基於應用A和孩子創建事件 處理程序邏輯,使用fn2這裏。

class B : public A{ 
public: 
    B(); 
    void fn2(); 
}; 

B::B() { 
    A::setFn1(&fn2); 
} 

void B::fn2() {...} 

當我打電話:A::setFn1(&fn2)我得到以下編譯器錯誤。

#169 argument of type "void (B::)()" is incompatible with parameter of type "void ()()

我的腦子糊塗所有這些空洞的指針,如果我甚至使用了正確的設計了,我不知道。 A類包含我所有的實用方法。 B類包含我的應用程序特定功能。

+3

這些不是空指針!它們是指向不帶任何參數但不返回任何內容的函數的指針。 – 2013-04-04 19:07:41

回答

2

When I call: A::setFn1(&fn2) I get the following compiler error.

fn2B成員函數,所以必須限定它的名字:

A::setFn1(&B::fn2) 
//   ^^^ 

此外,fn2應該是static,因爲非static成員函數實際上是在一個工作隱含this指針,所以他們接受一個參數:

class B : public A{ 
public: 
    B(); 
    static void fn2(); 
// ^^^^^^ 
}; 

有了這兩個改變,你的程序應該編譯。

+0

當我做了A :: setFn1(&B :: fn2)時,出現以下編譯錯誤: #278名稱後跟「::」必須是類或名稱空間名稱。此外,這可能是設計問題,因爲我需要fn2是非靜態的,因爲它需要使用非靜態成員變量。 – zam664 2013-04-04 19:18:43

+0

@ zam664:你確定你正在複製一切嗎?它編譯[here](http://liveworkspace.org/code/3SRz1U$74)。 – 2013-04-04 19:21:58

+0

如果我讓fn2()是靜態的 - 是的,它編譯。但我需要非靜態來訪問成員變量,並且它不能編譯。我真的覺得我有一個設計問題,因爲我需要跨越這個靜態/非靜態障礙。 – zam664 2013-04-04 19:41:47

3

非靜態成員函數不是一個自由函數,類型不同。不能使用非靜態成員函數,如果它是一個指向函數:

struct test { 
    void foo(); 
    static void bar(); 
}; 

&test::foo --> void (test::*)() 
&test::bar --> void (*)() 

我不會爲您推薦改變函數爲static,因爲我不覺得現在是差不多設計特別有用。但是,你可以嘗試重新思考一個更有意義的設計。 (單回調功能適用於所有的過程?爲什麼繼承呢?一個用戶定義構造,做同樣的編譯器生成呢?不應該被實例化?一類...)

+0

我正在使用一個微控制器,我需要掛接到中斷表。我有這些中斷調用我的基類的靜態成員。父類是實用類,而子類將是應用程序類 - 它們都是單例類。現在所有的代碼都在C中。我想通過將它引入C++來利用OOD,但是我遇到了這個機器級接口的問題。 – zam664 2013-04-04 19:28:46

+0

@ zam664:您應該瞭解平臺中的調用約定,並且您可能需要添加'extern「C」'。繼承的使用毫無意義。爲什麼派生類型不直接註冊函數與中斷,爲什麼額外的間接?即使你想間接尋址,'A'沒有你需要模擬的*接口*,'B'可以完全不相關(這可能更有意義)。你也可以使用一個普通的舊的免費功能,利用OOD和錘擊OOD到處都是不同的東西,使用更適合任務的工具。 – 2013-04-04 19:55:27