2013-04-06 103 views
2

我想將一個函數指針傳遞給一個類的構造函數。但是,當我嘗試編譯代碼時,出現錯誤。代碼和錯誤是:在構造函數中的C++函數指針

quickfind.h

#ifndef QUICKFIND_H 
#define QUICKFIND_H 
#endif // QUICKFIND_H 

template <class T> 
class QuickFind 
{ 
private: 
    int size; 
    int *array; 
    int (*giveIndex)(const void *a); 
public: 
    QuickFind<T>(int n,int (*ptr)(const void *)); 
    void connect (const T* u,const T* v); 
    bool isConnected(const T* u,const T* v); 
}; 

構造函數定義在文件quickfind.cpp

template <class T> 
QuickFind<T>::QuickFind(int n,int (*ptr)(const void *)) 
{ 
    size=n; 
    array=new int[n]; 
    giveIndex=ptr; 
    for(int i=0;i<n;i++) 
    { 
     array[i]=i; 
    } 
} 

在我的主要功能文件:

int giveIndex (const void *ptr) 
{ 
    temp *tptr=(temp*)ptr; 
    return tptr->getA(); 
} 

int main() 
{ 
    QuickFind<temp> *qf=new QuickFind<temp>(10,giveIndex); 
} 

在這裏,我我得到'undefined reference to QuickFind<temp>::QuickFind(int, int (*)(void const*))'錯誤。我無法弄清楚問題......請幫忙。

+1

退房[爲什麼模板只能在頭文件中實現?(http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-頭文件)的細節。另外,在頭文件中包含守衛是很奇怪的... – 2013-04-06 15:11:47

回答

2

一點毛病,你不需要在構造函數:

template <class T> 
class QuickFind 
{ 
private: 
    int size; 
    int *array; 
    int (*giveIndex)(const void *a); 
public: 
    QuickFind(int n,int (*ptr)(const void *)); /// <---- here, no <T> 
    void connect (const T* u,const T* v); 
    bool isConnected(const T* u,const T* v); 
}; 

在你的情況下,模板類,但這個功能是沒有的。而且,必須在頭文件中定義模板函數,以便包含它們的文件可以看到代碼並替換參數類型。

+0

它給出了同樣的錯誤... – tigerden 2013-04-06 15:15:14

+0

閱讀我的評論。 .cpp文件中不能有模板實現。 – 2013-04-06 15:18:34

+0

我在quickfind.h的結尾添加了#include「quickfind.cpp」。然後通過g ++逐個編譯所有的頭文件和.cpp文件。最後在編譯爲'g ++ quickfind.o tempclass.o tempmain.o -o tempmain.exe'時出現同樣的錯誤。 – tigerden 2013-04-06 15:23:37

0

編譯器想要知道在編譯模板類方法時哪些類型將從模板類實例化的對象。因此,可能會出現編譯時或鏈接時錯誤。 This解釋更多關於各種錯誤及其原因。

在文件頭文件的末尾添加#include "quickfind.cpp"經過一番努力後在我的情況下工作。

2

將以下所有內容放入一個CPP文件中以查看其工作。正如其他評論中指出的那樣,對於模板類,必須將整個定義放在頭文件中。不要將函數聲明與其定義分離到單獨的CPP文件中。在這種情況下,在一個CPP文件中具有完整的實現用於相同的目的。

我對代碼進行了一些更改,使其具有類型安全性,內存泄漏安全性和更多的異常安全性。例如,我用std :: vector替換了動態分配的數組。 std :: vector具有您需要的所有功能,但是可以爲您管理內存,並在您的課程超出範圍時進行清理。

#include <vector> 
#include <iostream> 
#include <functional> 

template <typename T> 
class QuickFind 
{ 
private: 
    std::vector<int> data; 
std::function<int (const T&)> func; 
public: 
    QuickFind(int n, std::function<int (const T&)> f) : data(n), func(f) 
    { 
     int i = 0; 
     for(auto it = data.begin(); it != data.end(); ++it) 
      data[i]=i++; 
    } 

    void connect (const T& u, const T& v) 
    { 
     std::cout << func(u) << "\n"; 
     std::cout << func(v) << "\n"; 
    } 
    bool isConnected(const T* u,const T* v); 
}; 

class temp 
{ 
    int val; 
public: 
    temp(int i) : val(i) 
    {} 

    int getA() const 
    { 
     return val; 
    } 
}; 

int giveIndex (const temp &t) 
{ 
    return t.getA(); 
} 

int main() 
{ 
    temp t1(5), t2(10); 

    QuickFind<temp> qf1(10,giveIndex); 
    qf1.connect(t1, t2); 

    // this example uses a lambda as the callback 
auto giveIndex2 = [](const temp& t) { return t.getA(); }; 
QuickFind<temp> qf2(20, giveIndex2); 
qf2.connect(t1, t2); 
}