首页 > 试题广场 >

以下程序在32位机器上运行输出是____。

[单选题]
以下程序在32位机器上运行输出是____。
#include<iostream>
using namespace std;
class animal
{
protected:
    int age;
public:
    virtual void print_age(void) = 0;
};
class dog : public animal
{
public:
       dog() {this -> age = 2;}
       ~dog() { }
       virtual void print_age(void) 
       {
           cout<<"Wang, my age = "<<this -> age<<endl;
       }
};
class cat: public animal
{
public:
    cat() {this -> age = 1;}
    ~cat() { }
    virtual void print_age(void) 
    {
        cout<<"Miao, my age = "<<this -> age<<endl;
    }
};
int main(void)
{
    cat kitty;
    dog jd;
    animal * pa;
    int * p = (int *)(&kitty);
    int * q = (int *)(&jd);
    p[0] = q[0];
    pa = &kitty;
    pa -> print_age();
    return 0;

}
  • Wang, my age = 2
  • Wang, my age = 1
  • Miao, my age = 2
  • Miao, my age = 1
  • 程序编译报错
  • 程序运行报错
dog jd 。。。 阿里太坏了
发表于 2015-08-23 00:29:20 回复(4)
啥头像
答案为 B。

含有虚函数的类的对象在内存的第一项是指向虚函数表的指针

p[0] = q[0];把q的虚表指针赋给了p的第一项

但是后面的内容没有变,age没有变

pa指向kitty,交换指向虚函数表的指针后,pa调用jd的print_age,显示的kitty的age

编辑于 2015-09-10 16:33:04 回复(2)
B:带有虚函数的类中 首先产生VPTR 找到VTABLE
注意:原文认为(int*)(&b)是虚表的地址,我认为:(int *)*(int*)(&b)才是虚表地址
而(int*)*((int*)*(int*)(&b)); 才是虚表第一个虚函数的地址

且按照原文
p 是类cat的虚表指针
q 是类dog的虚表指针

p[0] 指向cat的第一个函数
q[0]指向dog的第一个函数

p[0] = q[0]  则p[0]  指向dog的第一个函数  则输出为wang age=
类成员变量不变  1
则结果为B

发表于 2015-04-27 16:31:55 回复(3)
首先这里需要清楚几个概念:
1.类的首地址一般是指向类的第一个成员变量的地址,但是如果类中含有虚函数那么类内存中头4字节指向的是虚函数表指针项(32bit系统),那么p[0] =  q[0];把q[0]的虚指针给了p,那么调用p当中的虚函数就不再是原来的那个虚函数了,而是新赋值的。
2.类的函数参数中都默认带有this,这里是编译器编译的时候生成的,一般我们看不见。那么这里当我们调用kitty这个类的函数的时候传递的this还是指向原来的cat类对象,但是调用的函数是dog里的函数。所以这题答案就明确了。
发表于 2021-03-21 23:44:52 回复(1)
通过实测。并稍加改动可以大致认为对象的内存地址是:
虚指针(如果有),数据成员列表;
故这里其实是改变了虚函数指针。
同样方式我们可以p[1] = 100;改变kitty 的 age 为100
编辑于 2015-08-22 15:12:47 回复(3)
我来分析下出题人的意思😂:
把自己写成kitty(而不是cat),把对手写为dog(而不是puppy),从英语的语义上,说明阿里比京东小(阿里2003成立,京东1998年成立);
自己实际的相对年龄为1,对手为2,最后age却输出为2,说明虽然经营时间我比你短,但经验上的年龄,我已经达到你的水平,将要赶上你了;
发表于 2020-11-28 15:39:26 回复(2)
cat Tmall 不好吗?
发表于 2018-05-10 16:09:25 回复(0)
1、带有虚函数的类,其实例内存最前面是虚函数表的地址;
2、通过(int *)可以得到虚函数表的地址
34、35行分别获得cat类 Kitty 和dog类 jd的虚函数表地址
36行修改了kitty的虚函数表地址。
因此在动态绑定中,pa访问的是修改后的虚函数表,即为jd的虚函数表,因此调用jd::print_age()
发表于 2016-09-04 17:22:42 回复(0)
覆盖掉的是虚表指针,而成员变量没有替换
发表于 2015-08-21 16:46:57 回复(0)
发表于 2023-10-30 20:11:32 回复(1)
p[0] = q[0] 相当于改变了内存布局中p的虚表指针的值,使得p的虚表指针的值为q的虚表指针的值。
编辑于 2015-08-22 15:13:12 回复(0)
这个考的好像是虚表指针的位置,和类的内存空间分布有关
编辑于 2024-01-07 16:10:02 回复(0)
64位系统下 vs2019 的输出结果和答案是一样的,为什么置换虚表不是用longlong类型????
发表于 2023-11-04 17:49:32 回复(0)
【C++ 虚指针、成员变量与类对象的偏移地址 - 代码先锋网】https://www.codeleading.com/article/91111813681/
发表于 2022-09-21 16:09:38 回复(0)
虚函数产生的vptr指针在内存首地址处,所以选b,age不便,执行的是狗的虚函数
发表于 2022-03-04 19:45:54 回复(0)
错题  类对象的虚表并非必须定义在类的开头,同样可以定义在类的结尾,由编译器自行实现,p[0]=q[0]属于未定义的
发表于 2022-02-28 08:54:08 回复(0)
补充说明:age=1是因为调用类成员函数的时候隐式的传入了this指针,对象地址没有变,所以age也没有变
发表于 2015-08-22 21:02:43 回复(0)
覆盖掉的是虚表指针。
发表于 2015-08-21 16:16:02 回复(0)
64位系统  vs2013中运行结果为:Wang, ma age = -858993460,(引用地址8位的缘故?)
编辑于 2015-08-22 15:13:03 回复(0)