class A {
public:
A() {}
virtual ~A() {}
virtual void f();
};
int main() {
A* a = new A();
return 0;
}
/usr/bin/ld: /tmp/ccc31LMa.o: warning: relocation against `_ZTV1A' in read-only section `.text._ZN1AC2Ev[_ZN1AC5Ev]'
/usr/bin/ld: /tmp/ccc31LMa.o: in function `A::A()':
c.cpp:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0xb): undefined reference to `vtable for A'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
原理其实和包含纯虚函数的类无法实例化一样。vptable不安全。
同理就算是继承了也是一样的无法实例化。如下
class VA {
public:
VA() {}
~VA() {}
virtual void f();
};
class VB : public VA {
public:
virtual void f() override {}
};
int main() {
VB* vb1 = new VB();
return 0;
}
/usr/bin/ld: /tmp/ccPm49yl.o: warning: relocation against `_ZTV2VA' in read-only section `.text._ZN2VAC2Ev[_ZN2VAC5Ev]'
/usr/bin/ld: /tmp/ccPm49yl.o: in function `VA::VA()':
c.cpp:(.text._ZN2VAC2Ev[_ZN2VAC5Ev]+0xb): undefined reference to `vtable for VA'
/usr/bin/ld: /tmp/ccPm49yl.o:(.data.rel.ro._ZTI2VB[_ZTI2VB]+0x10): undefined reference to `typeinfo for VA'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
虚函数只有声明没有实现就会有上述的链接问题。
但是如果将VA的f函数改成如下的纯虚函数如下,上述代码是可以编译运行的,VB可以实例化。
class VA {
public:
VA() {}
~VA() {}
virtual void f() = 0;
};
虚的析构函数也是同样的道理需要定义,不然也是会有undefined reference to vtable的问题。