编译器如何生成模板类定义
How does compiler generate template class definitions?
考虑以下头文件。
在我的Object.h
中
#ifndef OBJECT_H_
#define OBJECT_H_
#include <iostream>
template <class Policy>
class Object
{
friend Policy;
private:
Policy* p;
int hash;
public:
Object():p(new Policy(this)),hash(0){}
~Object(){delete p;}
void set(){p->setHash();}
void show() const{std::cout<<"hash = "<<hash<<std::endl;}
};
#endif // OBJECT_H_
然后,我创建了两个具有不同哈希值的策略P1和P2。
在p1.h
中
#ifndef P1_H_
#define P1_H_
template <class Policy> class Object;
class P1
{
enum {p1 = 1};
Object<P1>* t;
public:
P1(Object<P1>* at):t(at){}
void setHash(){t->hash = p1;}
};
#endif // P1_H_
在p2.h
中
#ifndef P2_H_
#define P2_H_
template <class Policy> class Object;
class P2
{
enum {p2 = 2};
Object<P2>* t;
public:
P2(Object<P2>* at):t(at){}
//void setHash(){t->hash = p2;} // ** Notice here **
};
#endif // P2_H_
在我的main.cpp
中,我有
#include "Object.h"
#include "p1.h"
#include "p2.h"
int main()
{
Object<P1> t1;
t1.set();
t1.show();
Object<P2> t2;
//t2.set();
t2.show();
}
操作系统X上的结果:
hash=1
hash=0
观察:
它将正确编译和运行。请注意,
Object<P2>
的定义甚至还不完整。由于P2尚未定义setHash()。如果我删除了main中的注释,那么它将报告一个错误。
/Object.h:20:8:错误:"P2"中没有名为"setHash"的成员
main.cpp:12:6:注意:在实例化成员函数"Object::set"时,此处请求t2.set();
问题
考虑一下P1或P2类中的Object成员,即使我没有在main中创建
Object<P1>
或Object<P2
的实例,编译器也会为它们中的每一个生成类定义吗?为什么
Object<P2>
可以?由于定义不完整。
考虑一下P1或P2类中的Object成员,即使我没有在main中创建
Object<P1>
或Object<P2>
的实例,编译器也会为它们中的每一个生成类定义吗?
没有。成员是Object<P1>* t;
和Object<P1>* t;
——它们不是static
,所以只有在创建P1
和P2
对象实例时才会创建,而且它们是指针,所以即使在那时也不会创建Object<P1>*
:传递给构造函数的指针(可能是nullptr
/0
)也会被简单地存储。
为什么对象可以?由于定义不完整。
对于模板,函数只有在被调用时才会被实例化。只要它们能够被正确地解析,这就不是错误。
在P1
和P2
中没有Object<P1>
或Object<P2>
成员。共有Object<P1>*
和Object<P2>*
两个成员。指向不完整类型的指针完全可以。除非取消引用指针,否则类型本身不会被实例化。
在main
函数中,Object<P2>
是一个完整的类型,但它的非虚拟成员函数仍然不会实例化,除非调用(或者更确切地说,从技术上讲,使用ODR)。这就是为什么有Object<P2> t2;
是可以的,但调用t2.set()
是一个错误。
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 从用户定义的类生成格式字符串?
- 如何为每个客户生成自定义 exe
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- C++/生成文件错误:未定义对"main"的引用
- 生成文件缺少包含路径 尽管路径存在并已定义
- G++ 编译器未为未定义的方法生成错误/警告
- 生成文件:体系结构x86_64的未定义符号
- 为什么虚拟方法生成对_sbrk的未定义引用?
- 获取生成错误:错误 C2011:'ProfileSettings':'class'类型重定义
- 如何使用independent_bits_engine定义要生成的位数
- 如何在不重新发明轮子的情况下为自定义类型生成均匀分布的随机实数
- 类外的成员模板函数定义无法生成Visual studio 2013
- 调整定义/包含生成的结构以增强::融合
- 位结构定义语言生成c++代码
- 多函数定义错误生成文件
- 在其定义中生成实例
- 编译器不允许定义编译器生成的构造函数
- 定义一个生成元素向量的函数时,正确的方法是什么?