2016-09-14 61 views
4

我有幾個void函數在我的代碼中執行一些重要的事情。函數期望參數並返回指向void函數的指針

void function1(Myclass class1, int myvar) 
{ 
    // do some stuff 
} 

void function2(Myclass class1, int myvar) 
{ 
    // do some other stuff 
} 

// ... maybe some more similar functions 

我想創建一個函數,根據我傳遞的參數返回一個指向這些函數的指針。我不知道該怎麼做。我想有類似的東西

void* choosefunction(int i, int j) 
{ 
    if (i == j) return (void*)function1; 
    else return (void *)function2; 
} 

然後,我只是通過這個指針調用它們。

void *(*ptrProcFunc)(int,int); 
ptrProcFunc = &choosefunction; 
(*ptrr)() = ptrProcFunc(i,j); 
ptrr(class1,myvar); 

如何正確地做到這一點?謝謝。

回答

6

typedef是你的朋友。

typedef void (*func_ptr)(Myclass, int); 

func_ptr choosefunction(int i, int j) 
{ 
    if (i == j) return &function1; 
    else return &function2; 
} 

然後:

func_ptr ptrr = choosefunction(i,j); 

ptrr(class1,myvar); 
+0

你是正確的,感謝指出了這一點。 –

+0

另一個選擇是不使用指針類型定義,當任何指針聲明中總是有一個'*'時,IMO代碼更易於讀取 –

+1

如果C++ 11或更高版本可用,我會提供別名形式:'func_ptr = void (Myclass,int);'我認爲它更清晰。 –

1

下面是一個完整的例子。

#include <functional> 
#include <iostream> 

// Typedef for convenience, called "fcn". 
typedef void(*fcn)(int, int); 

// You could also use c++11's std::function, which is easier 
// to read than function pointers. 
typedef std::function<void(int, int)> modern_fcn; 

void func1(int a, int b) { 
    std::cout << "func1" << std::endl;  
} 

void func2(int a, int b) { 
    std::cout << "func2" << std::endl; 
} 

// This returns our typedef'd function pointer. 
fcn pick(int i, int j) { 
    if (i == j) { 
     return &func1; 
    } else { 
     return &func2; 
    } 
} 

int main() 
{ 
    // Should call func1. 
    pick(1,1)(3, 5); 

    // Should call func2. 
    pick(1,2)(3, 5); 
} 
1

您有幾種選擇:

  • 您可以使用using聲明引入一個別名你的類型:

    using func_ptr = void (*)(Myclass, int); 
    using choose_ptr = void *(*)(int,int); 
    
    // ... 
    
    func_ptr choosefunction(int i, int j) { 
        if (i == j) return &function1; 
        else return &function2; 
    } 
    
    // ... 
    
    choose_ptr ptrProcFunc = &choosefunction; 
    func_ptr ptrr = ptrProcFunc(i,j); 
    ptrr(class1,myvar); 
    
  • 您可以使用auto符和這就是全部(C++ 14):

    auto choosefunction(int i, int j) { 
        if (i == j) return &function1; 
        else return &function2; 
    } 
    
    // ... 
    
    auto ptrProcFunc = &choosefunction; 
    auto ptrr = ptrProcFunc(i,j); 
    ptrr(class1,myvar); 
    
  • 您可以使用auto符和從動型(C++ 11):

    auto choosefunction(int i, int j) -> decltype(&function1) { 
        if (i == j) return &function1; 
        else return &function2; 
    } 
    
    // ... 
    
    auto ptrProcFunc = &choosefunction; 
    auto ptrr = ptrProcFunc(i,j); 
    ptrr(class1,myvar); 
    

    在這種情況下,我們利用以下事實:function1function2有相同的類型。

1

的(醜陋)語法是

void (*choosefunction(int i, int j))(Myclass, int) 
{ 
    if (i == j) return &function1; 
    else return &function2; 
} 

隨着using(或typedef)時,它變爲可讀:

using F = void(Myclass, int); 
using FPtr = void(*)(Myclass, int); // or using FPtr = F*; 

然後

F* choosefunction(int i, int j); 

FPtr choosefunction(int i, int j); 

,如果你在線的定義,您可以在C++ 14使用簡單auto

auto choosefunction(int i, int j) { 
    if (i == j) return &function1; 
    else return &function2; 
} 

無論如何,用法是這樣的:

FPtr f = choosefunction(i, j); 

f(myclass, myvar); 
1

你的困惑(和我在很多學習C或C++的人看來,這是),那些是不是「無效函數」。最好的情況是,你可以說它們是不返回任何東西的函數(如果你更輕鬆一些,並且濫用語言,我們可以說它們是返回void的函數)。他們是函數接收Myclassint的論點,並沒有返回

其他答案告訴你如何做到這一點。我強烈建議您使用using代替typedef,尤其是對函數類型:

using func_ptr = void (*)(Myclass, int); 

混亂(我認爲)的來源是你先學變量聲明:

int a 

並且您知道聲明的實體的類型在其左側被命名。

然後你學習功能和你寫的:

int sum(int a, int b) 

而且通過(錯)比喻你說:在實體被聲明爲sum所以它的類型必須是寫在上面還剩下些什麼,即int 。所以你說「總和是int」,這是錯誤的,並引起像你OP中的混亂。

sum的類型是「函數接收兩個整數作爲參數並返回一個整數」。

爲了幫助你擺脫你的習慣,寫或至少覺得在新的尾隨返回類型聲明語法功能:

auto sum(int a, int b) -> int