首页 > 试题广场 >

写出程序的运行结果

[单选题]

写出程序的运行结果

#include<iostream>
using namespace std;

class Base
{
    int x;
public:
    Base(int b): x(b) {}
    virtual void display()
    {
        cout << x;
    };
};
class Derived: public Base
{
    int y;
public:
    Derived(int d): Base(d), y(d) {} void display()
    {
        cout << y;
    }
};

int main()
{
    Base b(1);
    Derived d(2);
    Base *p = & d;
    b.display();
    d.display();
    p->display();
    return 0;

}



  • 121
  • 222
  • 122
  • 运行出错
推荐
C 本题主要考察的是基类与派生类的赋值兼容概念。首先,Base b(1)是为基类(Base)对象b开辟一个大小为4个字 节的内存空间用于 存放成员变量b.x的值并赋值为1;
其次,派生类 Derived d(2) 是为派生类(Derived)对象d开辟一个大小为8个字 节的内存空间(其中4个字节存放成员变量d.x并赋值于2,
4个字节存放 成员变量d.y的并赋值为2); 最后,d(2) Base *p = & d是把 派生类对象的地址&d赋值给指向基类对象的指针变量p。通过指向基类对象的指针,只能访问派生类中的基类成员,而不能访问派生类增加的成员。
编辑于 2016-09-15 09:32:22 回复(2)
答案:C。
在面向对象中,多态指的是使用相同的函数名来访问函数不同的实现方法,
即“一种接口,多种方法”,用相同的形式访问一组通用的运算,
每个运算可能对应的行为不同。C++语言支持编译时多态和运行时多态,
其中,编译时多态指的是系统在编译时能确定调用哪个函数,
它具有执行速度快的优点,运算符重载和函数重载就是编译时多态。
运行时多态指的是系统在运行时动态决定调用哪个函数,
它为系统提供了灵活和高度问题抽象的优点,通过继承和虚函数实现运行时多态。
运行时多态的基础是基类指针,基类指针可以指向任何派生类对象。
在基类中的某成员函数被声明为虚函数后,在之后的派生类中可以被重新定义。
但在定义时,其函数原型,包括返回类型、函数名、参数个数和参数类型的顺序,
都必须与基类中的原型完全相同。只要在基类中显式声明了虚函数,
那么在之后的派生类中就不需要用关键字virtual来显式声明了,可以略去,
因为系统会根据其是否和基类中虚函数原型完全相同来判断是不是虚函数。
所以,派生类中的虚函数如果不显式声明也还是虚函数。
对于虚函数,有几点内容需要引起读者注意:
1)因为虚函数使用的基础是赋值兼容
(赋值兼容是指在需要用到基类对象的任何地方都可以用公有派生类的对象来代替),
而赋值兼容成立的条件是派生类从基类public继承而来。所以,当使用虚函数时,
派生类必须是基类public派生的。
2)定义虚函数时,不一定要在最高层的类中,
而是看在需要动态多态性的几个层次中的最高层类中声明虚函数。
3)只有通过基类指针来访问虚函数才能实现运行时多态的特性。
4)一个虚函数无论被公有继承了多少次,它仍然是虚函数。
5)虚函数必须是所在类的成员函数,而不能是友元函数,也不能是静态成员函数。
因为虚函数调用要靠特定的对象类决定该激活哪一个函数。
6)内联(inline)函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的,
即使虚函数在类内部定义,编译时将其看作非内联。
7)构造函数不能是虚函数,但析构函数可以是虚函数。
本题中,Base b(2)定义了一个父类的对象b,
语句b.display()会调用Base的display方法输出1。
而d的类型为Derived,因此,语句d.display()会调用Derived的display方法输出2。
虽然p是指向Derived类型的指针,但它实际上指向的是子类的对象,
因此,p->display()函数调用的是派生类的display()函数(多态),输出为2。
所以,选项C正确。

编辑于 2018-08-24 09:00:22 回复(2)
多态的条件,这里是自己做一个笔记,理解可能有偏颇。表达也可能不规范。 ①父类指针指向子类对象; ②虚函数重写; 然后父类指针调用虚函数,p只像一个父类对象,在这里p->display()是发生了多态的,因此它调用的不是父类的display函数,而是子类的display函数。所以答案中的122中的最后一个2就是这样来的。
发表于 2020-03-24 23:19:20 回复(0)
发表于 2019-05-07 14:34:32 回复(0)
C++ Primer里说:如果调用的函数是实函数,则看指针的定义;如果调用的函数是虚函数,则看指针的指向(赋值)
发表于 2017-07-05 09:46:09 回复(0)

在这道题中,通过声明和实现了虚函数display(),可以实现动态绑定。

首先,创建了一个Base类对象b,并将其初始化为1。然后,创建了一个Derived类对象d,并将其初始化为2。接着,使用基类指针p指向Derived对象d,这是允许的,因为Derived是Base的派生类。

在调用display()函数时,使用了虚函数的动态绑定机制:

  1. b.display():由于b是Base类型的对象,编译器会根据静态类型Base来查找对应的函数。然而,在运行时,实际对象是Base类型,因此调用Base类的display()函数,并输出结果1。
  2. d.display():d是Derived类型的对象,编译器会根据静态类型Derived来查找对应的函数。由于display()函数在Base类中被声明为虚函数,在Derived类中也重新定义了该函数。在运行时,实际对象是Derived类型,因此调用Derived类的display()函数,并输出结果2。
  3. p->display():p是指向Base对象的指针,但指向的是Derived对象d。使用了虚函数的动态绑定机制,在运行时,根据实际对象是Derived类型,因此调用Derived类的display()函数,并输出结果2。

因此,程序的运行结果是122。

发表于 2023-10-19 16:15:32 回复(0)
单纯考虑调用OK了
发表于 2021-04-20 16:21:52 回复(0)
实函数看指针定义,虚函数看指针指向
发表于 2023-09-19 08:13:54 回复(0)
C 本题主要考察的是基类与派生类的赋值兼容概念。首先,Base b(1)是为基类(Base)对象b开辟一个大小为4个字 节的内存空间用于存放成员变量b.x的值并赋值为1;
其次,派生类 Derived d(2) 是为派生类(Derived)对象d开辟一个大小为8个字 节的内存空间(其中4个字节存放成员变量d.x并赋值于2,
4个字节存放 成员变量d.y的并赋值为2); 最后,d(2) Base *p = & d是把 派生类对象的地址&d赋值给指向基类对象的指针变量p。通过指向基类对象的指针,只能访问派生类中的基类成员,而不能访问派生类增加的成员。
发表于 2017-08-03 10:40:54 回复(0)
本题中是不是即使p->display();调用 Base下的display方法也是输出122的
发表于 2016-09-23 09:39:19 回复(1)
本题选C,主要考察类与派生类的知识,主要搞清楚是哪个类的对象调用哪个类的构造函数及成员方法。
发表于 2016-09-16 16:19:56 回复(0)
构造函数只调用一次
发表于 2016-06-23 18:20:06 回复(0)
类定义中,成员函数后的引号可加可不加
发表于 2016-01-17 10:40:00 回复(0)
C 考察虚函数
发表于 2015-06-12 09:40:23 回复(0)
C 考的虚函数
发表于 2015-04-01 12:22:37 回复(0)
答案 C
发表于 2015-01-11 16:23:48 回复(0)