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

C++类中的虚函数不能为模板函数相关推荐

  1. C++学习笔记-----永远不要在派生类中改变虚函数的默认参数值

    提到虚函数,我们就会自然而然的想到多态,但是当虚函数中存有默认参数值的时候,在派生类中重定义这个虚函数时不可以改变这个参数的值. 请看下面的例子: #include "stdafx.h&qu ...

  2. [FxCop.设计规则]16. 不要在封闭类中声明虚成员

    16.     不要在封闭类中声明虚成员 翻译概述: 一条比较无聊的规则,并且VB.NET和C#编译器都已经内嵌的禁止代码违反这条规则. 引起的原因: 一个公共的封闭类型中包含虚成员.这条规则不检查d ...

  3. C/Cpp / 模板类中可以使用虚函数吗?模板成员函数可以是虚函数吗?

    一.答案 前者是可以的,后者是不可以的. #include <iostream>template <class T> class Base { public:virtual v ...

  4. define宏定义函数及用模板函数实现同样的功能

    最近在看别人的代码的过程中,发现了宏定义代码,由于自己这块之前没有用过,所以编写了示例程序,学习一下宏定义代码. 比如我们现在有一个需求,要实现两个数字交换,这两个数字可能是整型,浮点型或者其他类型, ...

  5. C++多继承中重写不同基类中相同原型的虚函数

    在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA  {  public:  virtual void TestA();  };  class ...

  6. c++中的虚特性(虚基类、虚函数、纯虚函数)

    1. 虚基类 1.1 虚基类作用 为了解决多继承时的命名冲突和冗余数据问题,使得派生类中只保留一份间接基类的成员. 其本质是是让某个类做出声明,承诺愿意共享它的基类.其中,这个被共享的基类就称为虚基类 ...

  7. 避免在派生类中重新定义基类的非虚函数

    我们都知道,在基类中定义虚函数的目的是允许派生类拥有相同接口却可以有不同的实现,通过对象的指针或引用来访问虚函数可以实现运行时的多态.这么说来,在派生类中重定义(override)虚函数是没有任何问题 ...

  8. C++抽象基类和纯虚成员函数

    公共接口是指一系列成员函数的集合,支持该接口的类必须以合适的方式重新定义这些成员函数,否则就无法创建对象.在C++中,可以通过抽象基类来实现公共接口. 纯虚函数 纯虚成员函数的声明语法如下: virt ...

  9. C++中的虚函数(virtual function)

    1回顶部 一.简介 虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的函数.假设我们有下面的类层次: class A { public: virtua ...

最新文章

  1. AI开发人员使用频率最高的10个机器学习平台!
  2. 平流式隔油池计算_玻璃钢隔油池
  3. jsp jdbc mysql增删改查_使用JSP+SERVLET+JDBC实现对数据库的增删改查(详细)
  4. 余数运算符在Java中用于Doubles
  5. Cocos2d开发1:Xcode与TexturePacker的集成
  6. QtJava笔记-Qt与Java进行SSL双向认证(Qt客户端,Java服务端)
  7. mac安装go语言环境
  8. Shell脚本之grep
  9. C++_跳转语句continue_跳转语句goto_一维数组数组_数组定义_数组名---C++语言工作笔记019
  10. SQL SERVER将多行数据合并成一行(转载)
  11. js用户密码强度验证函数
  12. HTML5的革新:结构之美
  13. 用c语言在Clion平台编写system(“cls“)清屏函数无效甚至异常解决方法。
  14. autoCAD 向图形中添加文字
  15. ZZUOJ 公主与骑士 (BFS)
  16. 本题要求编写程序,输出整数152的个位数字、十位数字和百位数字的值。
  17. php怎么彻底清楚,navicat怎么彻底删除
  18. 搞深度学习需掌握的基础数学知识
  19. 【唐诗学习】四、边塞诗派代表
  20. 俄罗斯方块实验报告(附源码)

热门文章

  1. VB6语言怎么对接验证码短信接口?
  2. MediaCodec
  3. 外链是什么意思,如何做好高质量的外链建设?
  4. 信道容量+平均互信息
  5. CALayer的动画跟一个播放音乐的demo
  6. M1芯片Mac快速查询硬盘读写情况
  7. 赌对周期,李想的汽车之家成长为市值10亿美元的公司(转)
  8. H264编码原理及NALU介绍
  9. 独一无二的NFT代币之快速指南
  10. 机器学习与分布式机器学习_机器学习适合所有人