C++模板,这次是真的不会了,求救
先上代码:
#include <iostream> class base { public: int send(){} }; class derived : public base { public: using base::send; }; template<class T> class maker { public: typedef int (T::*pf_t)(); template< pf_t pf > void def( const char *func_name ) { // do something ... } }; int main() { // 函数不是通过继承而来,OK // class maker<base> mk_base; // mk_base.def<&base::send>( "send" ); class maker<derived> mk; mk.def<&derived::send>( "send" ); return 0; }
编译错误:
g++ -o template template.cpp template.cpp: In function ‘int main()’: template.cpp:35:36: error: no matching function for call to ‘maker<derived>::def(const char [5])’ template.cpp:35:36: note: candidate is: template.cpp:22:10: note: template<int (derived::* pf)()> void maker::def(const char*) [with int (T::* pf)() = pf; T = derived] template.cpp:22:10: note: template argument deduction/substitution failed: template.cpp:35:36: error: could not convert template argument ‘&base::send’ to ‘int (derived::*)()’
首先,这是一段被我简化了的代码。之前这段代码用作C++与lua的交互,即将任意C++类注册到lua。可以看到,我们每特化一个class maker时,调用def函数都会特化pf_t这个变量。比如base类特化为int base::send(),derived则特化为int derived::send() 。
最近拓展功能时,想重用一些代码,于是使用了继承。但由于pf_t这个变量带有域,特化失败。即derived::send这个函数是不存在的,存在的是base::send。
不想重新拷一遍代码,有没有解决的办法呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(26)
看来只能覆盖基类,再调用基类了
这样在这里是OK的。但因为只能把static int (lua_State *L)这样的函数注册到lua,所以在def函数里还要进行另一个模板特化,也是同样的问题。
这样应该和楼主之前的代码调用方式变化不大 不知是否适用
我发现 在def函数模版参数中传入 derived::send时 g++会报找不到send , 必须要在derived类中实现send才可以通过, 我建议楼主将def函数的模版换成参数形式, 代码如下
这段是把send改写成static方式实现, 在外界调用时可以和楼主原本调用方式一致, 编译环境 MinGW4.9.1 win7
不知道题主要的是什么, 不知这样是否可以满足功能:
#include <iostream>
class base
{
public:
int send(){}
};
class derived : public base
{
public:
//virtual int send(){}
using base::send;
};
template<class T>
class maker
{
public:
typedef int (T::*pf_t)();
void def( pf_t fn, const char *func_name )
{
// do something ...
}
};
int main()
{
class maker<derived> mk;
mk.def(&derived::send, "send");
return 0;
}
这个没试过。decltype好像是C++11的。我们线上的centos6.5好像不支持
回复
"using base::send;"这个就是c++11的特性之一啊
using不C++11的吧。最简单的用法是using namespace std;这个很早的了
重新定义一下类型别名应该就行了吧
子类再实现一次肯定是可以的。关键是想重用基类的逻辑代码。当前在子类再调用一次基类也是可以的。只是看有没有更好的解决方案
#include <iostream>
class base
{
public:
virtual int send()=0;
};
class derived : public base
{
public:
using base::send;
int send(){
//do something;
}
};
template<class T>
class maker
{
public:
typedef int (T::*pf_t)();
template< pf_t pf >
void def( const char *func_name )
{
// do something ...
}
};
int main()
{
class maker<derived> mk;
mk.def<&derived::send>( "send" );
return 0;
}
g++编译成功
楼主这样可以吗?我是把父类中的send设为纯虚函数,只提供一个接口,继承类应该也要有实现的吧?
# g++ -o main main.cpp main.cpp: In function ‘int main()’: main.cpp:55: 错误:对‘maker<derived>::def(const char [5])’的调用没有匹配的函数 还是像我说的那样,&derived::send这个函数是找不到的
回复
之前没有在g++上测试 这里有个我改成static的 我发在下面
回复
对了我之前使用的vs2010编译器可以通过, 在g++环境下是需要在derived也实现send函数才能通过, 我是用的是 MinGW4.9.1
覆盖是可以解决,但是覆盖就要我多写一次代码了。就好比我没用继承,直接用了组合。derived是在程序运行时才实例化的,在lua层。这里只是特化模板。
&derived::send 这个写法是取derived的成员方法,实际上derived是没有该方法,即使base用虚函数也没用,他不会去vt里面找基类的方法。
这种实现方法不推荐,解决办法就是基类的Send加个virtual, 然后在derived里面覆盖Send方法,在Send方法里面调用基类的Send方法。
我很奇怪,你的derived实例在哪里?
vs2010 编译没有错误
def 声明为虚函数没有实际作用, 虚函数功能是体现在继承上, 这里楼主貌似是要调用base和其子类的send函数, 可将send定义为虚函数
def声明为虚函数试试
定义一个函数指针
回复
这个是类成员函数指针, 比函数指针多了类限定符
回复
嗯,一样的
第19行代码怪怪的,看不懂。