#include <iostream>
class Base1
{
private:
char aChar;
short aShort;
int aInt;
float aFloat;
};
class Derived1: public Base1
{
private:
char charArray[3];
short shortArray[3];
int intArray[3];
float floatArray[3];
Base1 *ptrBase1;
};
class Base2
{
public:
virtual ~Base2() {}
virtual void virtualMethod() { std::cout << "virtualMethod" << std::endl; }
private:
char aChar;
short aShort;
int aInt;
float aFloat;
};
class Derived2 : public Base2
{
public:
virtual ~Derived2() {}
private:
char charArray[3];
short shortArray[3];
int intArray[3];
float floatArray[3];
Base2 *ptrBase2;
};
int main()
{
Derived1 derived1;
std::cout << sizeof(Derived1) << std::endl;
std::cout << sizeof(Base1) << std::endl;
memset(&derived1, 0, sizeof(Derived1));
Derived2 derived2;
std::cout << sizeof(Derived2) << std::endl;
std::cout << sizeof(Base2) << std::endl;
memset(&derived2, 0, sizeof(Derived2));
derived2.virtualMethod(); // ok
Base2 *ptrBase2 = new Derived2();
memset(&ptrBase2, 0, sizeof(Derived2));
ptrBase2->virtualMethod(); // crashes here
delete ptrBase2;
return 0;
}
/*
56
12
64
24
virtualMethod
段错误 (core dumped)
*/
结论:
1. 由 sizeof 的结果对比可知,成员方法是要占用对象的空间的。不过奇怪的是 Base1 到 Base2 增加了 12 字节,Derived1 到 Derived2 却只增加了 8 字节。
2. derived2.virtualMethod() 并没有 crash, 而 ptrBase2->virtualMethod() 却 crash 了,说明只有【动态绑定】时才会 crash, derived2.virtualMethod() 是编译阶段就确定了,memset 不影响。个人猜想是【动态绑定】时需要根据 vtable 在运行阶段确定函数地址,而 memset 却修改了这个地址,导致 crash。
(https://vctipsplusplus.wordpress.com/tag/memset-and-virtual-function/)
综上,当类中存在虚函数(包括类成员,典型的如类成员中含有 STL 中的 std::string 等)时,不要使用 memset, 排除这点还是可以使用 memset 的(目前还没有遇到其它情况不能用 memset 的)。