C++模板,这次是真的不会了,求救

发布于 2021-11-28 15:40:27 字数 1603 浏览 694 评论 26

先上代码:


#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(26

三月梨花 2021-12-02 07:48:21

看来只能覆盖基类,再调用基类了

冷默言语 2021-12-02 07:48:21

这样在这里是OK的。但因为只能把static int (lua_State *L)这样的函数注册到lua,所以在def函数里还要进行另一个模板特化,也是同样的问题。

晚风撩人 2021-12-02 07:48:21

这样应该和楼主之前的代码调用方式变化不大 不知是否适用

落墨 2021-12-02 07:48:19

我发现 在def函数模版参数中传入 derived::send时 g++会报找不到send , 必须要在derived类中实现send才可以通过, 我建议楼主将def函数的模版换成参数形式, 代码如下

#include <iostream>
using namespace std;
 
class base
{
public:
    base()
    {
        cout << "base bae()";
    }
    virtual int send()
    {
        cout << "base send()";
        return 0;
    }
};
 
class derived : public base
{
public:
    derived()
    {
        cout << "derived derived()";
    }
    
};
 
template<class T>
class maker
{
public:
    maker()
    {
        m_t = new T;//send不是静态方法 所以需要创建对象
    }
    typedef int (T::*pf_t)();
 
    void def(pf_t pf, const char *func_name )
    {
        // do something ...
        cout << "funcname: " << func_name;
        (m_t->*pf)();
    }
    T *m_t; //这里保存模版类对象
};
 
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;
}

悸初 2021-12-02 07:48:18

这段是把send改写成static方式实现, 在外界调用时可以和楼主原本调用方式一致, 编译环境 MinGW4.9.1 win7

平定天下 2021-12-02 07:48:18

不知道题主要的是什么, 不知这样是否可以满足功能:

#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;
}

简单气质女生网名 2021-12-02 07:48:13

这个没试过。decltype好像是C++11的。我们线上的centos6.5好像不支持

坐在坟头思考人生 2021-12-02 07:48:13
#include <iostream>
using namespace std;

class base
{
public:
    base()
    {
        cout << "base bae()" << endl;
    }
    static int send()
    {
        cout << "base send()" << endl;
        return 0;
    }
};
 
class derived : public base
{
public:
    derived()
    {
        cout << "derived derived()" << endl;
    }
    static int send()
    {
        cout << "derived send()" << endl;
        return 0;
    }
};
 
template<class T>
class maker
{
public:
    typedef int (*pf_t)();

    template<pf_t pf >
    void def( const char *func_name )
    {
        // do something ...
        cout << "funcname: " << func_name << endl;
        pf(); //通过对象调用函数类成员函数指针, 或者把send改成静态
    }
};
 
int main()
{
    // 函数不是通过继承而来,OK
    class maker<base> mk_base;
    mk_base.def<&base::send>( "maker<base> send" );
 
    class maker<derived> mk;
    mk.def<&derived::send>( "maker<derived> send" );
     
    return 0;
}

居里长安 2021-12-02 07:48:02

回复
"using base::send;"这个就是c++11的特性之一啊

平定天下 2021-12-02 07:47:40

using不C++11的吧。最简单的用法是using namespace std;这个很早的了

辞别 2021-12-02 07:47:31

重新定义一下类型别名应该就行了吧

#include <iostream>
 
class base
{
public:
    int send(){}
    typedef decltype(&send)  pf_t;
};
 
class derived : public base
{
public:
    using base::send;
    typedef decltype(&send)  pf_t;
};
 
template<class T>
class maker
{
public:
    typedef typename T::pf_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;
}

刘备忘录 2021-12-02 07:47:28

子类再实现一次肯定是可以的。关键是想重用基类的逻辑代码。当前在子类再调用一次基类也是可以的。只是看有没有更好的解决方案

坏尐絯 2021-12-02 07:47:12

#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设为纯虚函数,只提供一个接口,继承类应该也要有实现的吧?

梦里兽 2021-12-02 07:47:08

# g++ -o main main.cpp main.cpp: In function ‘int main()’: main.cpp:55: 错误:对‘maker<derived>::def(const char [5])’的调用没有匹配的函数 还是像我说的那样,&derived::send这个函数是找不到的

眼眸 2021-12-02 07:44:25

回复
之前没有在g++上测试 这里有个我改成static的 我发在下面

路还长,别太狂 2021-12-02 07:40:34

回复
对了我之前使用的vs2010编译器可以通过, 在g++环境下是需要在derived也实现send函数才能通过, 我是用的是 MinGW4.9.1

丢了幸福的猪 2021-12-02 07:30:53
#include <iostream>
using namespace std;

class base
{
public:
	base()
	{
		cout << "base bae()";
	}
	int send()
	{
		cout << "base send()";
		return 0;
	}
};

class derived : public base
{
public:
	derived()
	{
		cout << "derived derived()";
	}
	using base::send;
};

template<class T>
class maker
{
public:
	maker()
	{
		m_t = new T;//send不是静态方法 所以需要创建对象
	}
	typedef int (T::*pf_t)();

	template< pf_t pf >
	void def( const char *func_name )
	{
		// do something ...
		cout << "funcname: " << func_name;
		(m_t->*pf)(); //通过对象调用函数类成员函数指针, 或者把send改成静态
	}
	T *m_t; //这里保存模版类对象
};

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;
}

//我认为3个方式可以解决 
//1. 声明send静态
//2. make中添加模版类型的对象实例化过程,并使用对象指针调用send, send
//3. 同2相似 send可以搞成virtual

多彩岁月 2021-12-02 07:07:39

覆盖是可以解决,但是覆盖就要我多写一次代码了。就好比我没用继承,直接用了组合。derived是在程序运行时才实例化的,在lua层。这里只是特化模板。

奢华的一滴泪 2021-12-02 07:05:32

&derived::send 这个写法是取derived的成员方法,实际上derived是没有该方法,即使base用虚函数也没用,他不会去vt里面找基类的方法。

这种实现方法不推荐,解决办法就是基类的Send加个virtual, 然后在derived里面覆盖Send方法,在Send方法里面调用基类的Send方法。

我很奇怪,你的derived实例在哪里?

网名女生简单气质 2021-12-02 04:55:16

vs2010 编译没有错误

小瓶盖 2021-12-02 04:23:32

def 声明为虚函数没有实际作用, 虚函数功能是体现在继承上, 这里楼主貌似是要调用base和其子类的send函数, 可将send定义为虚函数

梅窗月明清似水 2021-12-02 04:20:32

def声明为虚函数试试

凯凯我们等你回来 2021-12-02 03:11:11

定义一个函数指针

高跟鞋的旋律 2021-12-02 02:56:03

回复
这个是类成员函数指针, 比函数指针多了类限定符

夜司空 2021-12-01 20:11:17

回复
嗯,一样的

岁月打碎记忆 2021-12-01 15:36:43

第19行代码怪怪的,看不懂。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文