模板类 & 虚函数

 1 class faux
 2 {
 3 public:
 4     template <typename T>
 5     virtual void do()                    // member function templates cannot be virtual
 6     {}
 7 };
 8
 9
10 template <typename T>
11 class vrai
12 {
13 public:
14     virtual void do(T v)                // ok!
15     {}
16 };

为什么 faux 中不行呢?

因为如果 virtual function 是 template 的, 根据使用的不同类型, class faux 会有很多 do : do<int>,do<string> .....

而 c++ 要求在 faux 内存布局一定要在 faux 被实例前就确定(不确定怎么分配内存啊?);

但是如果 virtual function 是 template, 以后的使用中可能会有不确定数量的 do<>, 也就是说虚函数表确定不下来, 也就是说 faux 的内存布局确定不下来。

比如 faux 的一个实例:

faux * ff = new faux().
ff->do("hi");         // do<string>, 啊? 虚函数表增加了一项 virtual void do<string>
..................
ff->do(9527);        // do<int>, 啊? 虚函数表又增加了一项 virtual void do<int>
                      // !! 等等, 不是说 ff 实例化的时候内存布局(包括虚函数表)都要确定下来了吗?调用一个函数添加一个虚函数, 这就违反规则吗。
                      // 为什么虚函数表一定要确定下来呢?动态添加不是很cool? c++编译器提前 parse 一遍不就好了?
                      // 因为编译器在编译每个 cpp 的时候不管其他 cpp 的,只关心自己的编译单元。不同编译单元之间的引用那是 linker 的事。
                      // 如果 A.cpp B.cpp 同时包含了 class faux {...};
                      // 那么编译器编译 A.cpp 的时候增加了几个虚函数表项; 编译器编译 B.cpp 的时候也增加了几个虚函数表项, 那么就会冲突。
                      // 即便不冲突, 先编译A.cpp 增加了 1,2 项, 接着编译B.cpp 增加 3,4 项, 那么A.obj 看来 faux 的虚函数表只有两项, 而 B.obj 看来 faux 的虚函数表有 4 项。
                      // 这个是不一致的。所以为了避免这些问题, 就要求对象实例化之前虚函数表大小是确定的。

为什么 vrai 就可以呢?

由于 vrai 是 template class,他的实例化要等到具体使用时才确定。但是无论哪个实例

vrai<int> 还是 vrai<string> 他们的虚函数表总是确定的只有一个 virtual do。

时间: 2024-10-01 07:55:33

模板类 & 虚函数的相关文章

MFC浅析(7) CWnd类虚函数的调用时机、缺省实现

CWnd类虚函数的调用时机.缺省实现 FMD(http://www.fmdstudio.net) 1. Create 2. PreCreateWindow 3. PreSubclassWindow 4. PreTranslateMessage 5. WindowProc 6. OnCommand 7. OnNotify 8. OnChildNotify 9. DefWindowProc 10. DestroyWindow 11. PostNcDestroy CWnd作为MFC中最基本的与窗口打交

忍不住吐槽类模板、模板类、函数模板、模板函数

最近在查资料,发现了一些blog上写"类模板.模板类.函数模板.模板函数的区别"之类的文章.一看之下,闭起眼睛想想,自己写了这么久C++,知道模板,知道函数,也知道类.如果单独问我,类模板或者模板类,我都认为是采用了模板的类.但不知道这"类模板.模板类.函数模板.模板函数"是什么东西. 仔细看了下文章,忍不住吐槽了.其实就是采用模板的类叫类模板,实例化后叫模板类.采用模板的函数叫函数模板,实例化后叫模板函数.好吧,你赢了.知道模板的都会知道,模板实例化后会由编译器生

C++虚函数的陷阱--派生类对象的基类函数调用基类虚函数出错

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近写程序的时候发现,派生类对象的基类函数如果调用基类虚函数,则它将调用的是派生类的对应函数,而不是我想调用的基类的对应函数.</span> 下面用一个例子来说明: //基类 class Base { public: void funA(); virtual void fun

模板类成员函数的定义和声明为什么要放在一个文件中

"通常情况下,你会在.h文件中声明函数和类,而将它们的定义放置在一个单独的.cpp文件中.但是在使用模板时,这种习惯性做法将变得不再有用,因为当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明.因此,最好的办法就是将模板的声明和定义都放置在同一个.h文件中.这就是为什么所有的STL头文件都包含模板定义的原因."[1] "标准要求编译器在实例化模板时必须在上下文中可以查看到其定义实体:而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的--原因很简单

类模板、模板类、函数模板、模板函数

一:什么是类模板 一个类模板允许用户为类定义一种模式,使得类中的某些数据成员.默认成员函数的参数.某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的) 如果一个类中数据成员的数据类型不能确定.或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的.实际的类,而是代表一类类. 二:类模板定义及注意事项 template<class 模板参数表> 或者template<typename 模板参数表> class 类名 { /

类虚函数

理解C++中继承层次的关键在于理解如何确定函数调用,确定函数调用遵循以下四个步骤: (1)首先确定进行函数调用的对象,引用或指针的静态类型. (2)在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类.如果不能在类或其相关基类中找到该名字,则调用是错误的. (3)一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法. (4)假定函数调用合法,编译器就生成代码.如果函数是虚函数且通过引用或指针调用,则编译器生成代

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------&gt; 可以返回派生类对象的引用或指针

您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. 百度和网页 http://bbs.csdn.net/topics/380238133 的作者无关,不对其内容负责.百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面. 首页 精选版块 移动开发 iOS Android Qt WP 云计算 IaaS Pass/SaaS 分布式计算/Hadoop J

【整理】C++虚函数及其继承、虚继承类大小

参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/details/1948051/ 一.虚函数与继承 1.空类,空类单继承,空类多继承的sizeof #include <iostream> using namespace std; class Base1 { }; class Base2 { }; class Derived1:public Base1