class parent{
public: virtual void output();
};
void parent::output()
{
printf("parent!");
}
class son : public parent
{
public: virtual void output();
};
void son::output()
{
printf("son!");
}
则以下程序段:
son s;
::memset(&s , 0 , sizeof(s));
parent& p = s;
p.output();
执行结果是()
A、parent! B、son! C、son!parent! D、没有输出结果,程序运行出错
答案是D。应该很多人会选择B,跟我一样。。。主要是因为没看懂memset(&s , 0 , sizeof(s));这行的意思。
先说下多态吧。基类指针或引用可以引用派生类对象,注意引用不能引用临时变量,派生类重写了基类中的虚函数,在使用基类指针或引用调用时就会产生多态行为,也就是说实际调用的是派生类中的函数。如果去掉memset(&s , 0 , sizeof(s));这一行的话,答案就是B。
再说一下c++对象内存模型吧。c++编译器不允许不同对象有相同的内存地址,因此空类和空结构体大小为1(具体原因)。c++多态的实现机制,含有虚函数的类的每个对象,内部都有一个虚函数地址表指针,每个地址对应代码段中相应的虚函数。如果采用memset啥都不管就把整个对象的内存全置为0,那么虚函数表指针就空了,调用的时候找不到对应函数,运行出错!
还有一题
以下代码的执行情况是:
- class classA
- {
- public:
- classA()
- {
- clear();
- }
- virtual ~classA()
- {
- }
- void clear()
- {
- memset(this , 0 , sizeof(*this));
- }
- virtual void func()
- {
- printf("func\n");
- }
- };
- class classB : public classA
- {
- };
- int main(void)
- {
- classA oa;
- classB ob;
- classA * pa0 = &oa;
- classA * pa1 = &ob;
- classB * pb = &ob;
- oa.func(); // 1
- ob.func(); // 2
- pa0->func(); // 3
- pa1->func(); // 4
- pb->func(); // 5
- return 0;
- }
B、执行出错 func 执行出错 执行出错 func
C、执行出错 执行出错 执行出错 执行出错 执行出错
D、func func func func func
E、func func 执行出错 func func
F、以上选项都不对
答案是E,语句1、2执行没问题,3执行肯定出错,4和5具体原因还没弄清楚。。。难道是派生类对象在基类构造完成后,重新写了虚表指针?如果你知道,还请留言相告啊