C++类中的虚函数不能为模板函数

C++类中的虚函数不能为模板函数

首先,理解模板的原理。例如,定义了一个模板函数:

template<typename A>
void Func(const A& a) {
    std::cout <<"Func(const A& a) : "<< a << std::endl;
}

编译器在编译期间,会检查代码中哪些地方使用了这个函数,例如,如果在整个程序中使用到了两种类型:Func<int>(9);

Func<float>(9.3); 则编译器会生成两份函数的二进制代码:void Func(const int& a),以及void Func(const float& a)。

由于对于类的虚函数来说,其是否被调用是在程序运行的时候才知道,因此编译阶段不知道需要生成几份函数。    例如,基类是Base,有两个子类A和B, 代码中使用基类的指针来调用子类的虚函数 ,在编译阶段并不能知道调用的是哪个子类的虚函数,因此,编译器不知道类A和B中的模板函数被调用的情况,因此,不知道需要生成几份函数。

每个含有虚函数的类中都有一个虚函数表,该虚函数表存储着该类的所有的虚函数的地址,因此,虚函数为模板函数时,该表的大小是不知道的,因此编译器禁止!  虚函数为模板函数的情况下,编译阶段不能确定类的虚函数表的大小原因:下文有提到"However, the number of instantiations of a member function template is not fixed until the entire program has been translated". 例如,一般一个类定义在一个单独的文件中,编译器编译这个文件时并不知道其他文件对该类的virtual func的调用情况,所以无法确定模板虚函数的实例化个数!

但是,类的普通的成员函数是可以为模板函数的。例如A.h中定义了void A::f(T)这个模板函数,在main.cpp中使用该函数时需要#include A.h,然后编译器在编译main.cpp时应该会生成一份对应的模板实例。


From C++ Templates The Complete Guide:

Member function templates cannot be declared virtual.  This constraint is imposed because the usual implementation of the virtual function call mechanism uses a fixed-size table(虚函数表必须是fixed sized,我的盲点) with one entry per virtual function.     However, the number of instantiations of a member function template is not fixed until the entire program has been translated. Hence, supporting virtual member function templates would require support for a whole new kind of mechanism in C++ compilers and linkers. In contrast, the ordinary members of class templates can be virtual because their number is fixed when a class is instantiated.

Book:

C++ Templates - The Complete Guide, 2nd Edition

Test:

#pragma once
#include <iostream>
class templateFunc
{
public:
	void fun() {

	}

	//ok:
	template<typename A>
	void testFunc(const A& a) {
		std::cout << "templateFunc::testFunc(const A& a) : " << a << std::endl;
	}

	//error: 编译器会直接报错
	/*template<typename A>
	virtual void testMe(const A& a) {

	}*/
};

template<typename A>
void Func(const A& a) {
	std::cout <<"Func(const A& a) : "<< a << std::endl;
}

int main() {
	templateFunc obj;
	obj.testFunc<int>(6);

	Func<int>(9);
	return 0;
}

 可以结合模板函数与虚函数多态的机制

stack overflow上有人提到:

However, there are a few powerful and interesting techniques stemming from combining polymorphism and templates, notably so-called type erasure.

C++中的类型擦除(type erasure in c++)

C++: 类型擦除(type erasure)_Peace-CSDN博客_c++ 类型擦除

Ref:

Why class member function template can not be virtual in c++_creambean的博客-CSDN博客

c++ - Can a class member function template be virtual? - Stack Overflow

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值