现象
定义在内联函数时会有如下警告:
警告:'Sp_counter’没有行外的虚方法定义;它的虚函数表将在每个翻译单元中发出,意思就是程序编译时候会给每个有虚函数的类生成一个虚函数表然后放在.o里,程序运行后拷贝到内存里。
放在类外之后就正常了
原因
类的实例化就是给每一个实例在内存中分配一块地址。空类的大小是0,实例化时编译器会给一个字节。
class A {
public:
virtual ~A();
};
A::~A() {}
class AA {
public:
~AA() {}
};
int main() {
std::cout << sizeof(A) << ", " << sizeof(AA) << std::endl;
// 结果 8, 1 (gcc 64)
}
如果类中有虚函数,多8个字节(gcc 64)。任何有虚函数的类,都会多一个地址的大小,存放虚函数表的位置。为了高效,这个放地址的位置在这个类的存储空间最前面。
每一个有虚函数的类都有一个虚函数表,这个类的所有对象都放着这个表的指针。程序编译时候会给每个有虚函数的类生成一个虚函数表放在.o里,程序运行后拷贝到内存里。**
如果一个类是在头文件中定义的,并且有虚函数表(它有虚方法,或者它从有虚方法的类派生),那么它必须在类中至少有一个行外的虚方法。如果不这样做,编译器就会把vtable和RTTI复制到每一个包含了#include头文件的.o文件中,这会使.o文件的大小膨胀,并增加链接时间