2013-04-06 77 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); 
}