首页 > 试题广场 >

下列一段 C++ 代码的输出结果是()

[单选题]
下列一段 C++ 代码的输出结果是()
#include <iostream>
class Base{
 public:
     int Bar(char x){
         return (int)(x);
     }
     virtual int Bar(int x){
         return (2 * x);
     }
 };
 class Derived : public Base{
 public:
     int Bar(char x){
         return (int)(-x);
     }
     int Bar(int x){
         return (x / 2);
     }
 };
 int main(void){
     Derived Obj;
     Base *pObj = &Obj;
     printf("%d,", pObj->Bar((char)(100)));
     printf("%d,", pObj->Bar(100));
 }

  • 100,-100
  • 100,50
  • 200,-100
  • 200,50
推荐
答案:B
虚函数可以实现动态绑定。
 Base *pObj = &Obj;
这里讲pObj对象声明为Base类型,其实际类型是Derived类型
运行时,虚函数动态绑定,调用的是Base类中的Bar函数
非虚函数静态绑定,调用Derived类的Bar

编辑于 2015-01-19 20:59:06 回复(14)
首先看到pobj是BASE类型的,但又指向子类,当存在虚函数是,支持动态绑定,虚函数就可以指向子类了。
发表于 2019-02-25 12:11:23 回复(0)
答案:B
声明base类的指针指向derived类型对象。
首先遇到char类型实参调用形参为char类型的bar函数,因为base类中为虚函数,所以调用derived中该函数,输出100。
然后遇到int类型实参调用形参为int类型的bar函数,因为base类中该函数不为虚函数,所以使用它,输出50。
所以答案为100, 50。
发表于 2015-03-31 20:24:43 回复(1)
B 第一次调用了Base里的第一个Bar函数,第二次因为虚函数,调用的子类里的第二个Bar函数
发表于 2015-03-25 22:33:17 回复(0)
第一次调用非虚函数
第二次调用虚函数
发表于 2015-03-16 22:43:32 回复(0)
B
Derived Obj;
Base *pObj = &Obj;
printf("%d,", pObj->Bar((char)(100)))
printf("%d,", pObj->Bar(100));
第一个Bar(char)是非虚函数,因此是静态绑定,静态绑定是指指针指向声明时的对象,pObj声明时为Base类,因此调用的是Base类的Bar(char)
第二个Bar(char)是虚函数,因此是动态绑定,动态绑定是指指针指向引用的对象,pObj引用Derived对象,因此调用的是Derived类的Bar(int)

发表于 2015-04-10 16:40:34 回复(1)
B :指针pobj是基类,但指向的对象是子类,当方法Bar前有关键字VIRTUAL时,根据指针指向的对象的类型选择方法,当没有关键字virtual时,根据指针的类型选择方法,第一个方法没有关键字virtual,将根据指针的类型选择方法,也就是调用基类的bar()方法,第二个方法有关键字virtual,将根据指针指向的对象的类型选择方法,也即选择继承类的bar ()方法。
发表于 2015-04-07 16:19:21 回复(4)
指针是基类的,指向的对象是派生类对象;在为虚函数时,根据指针指向的对象类型调用相应的函数;若不是虚函数时,则根据指针类型调用相应的函数;在C++prime书里有说这些知识点
发表于 2018-09-08 11:15:28 回复(0)
其实很多理解独特的同学会疑惑为什么不是-100 50;
得出这个结果的是想到了重定义(隐藏):
1.如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无 virtual,基类的函数被隐藏。
2.如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 vitual 关键字,此时, 基类的函数被隐藏。
我刚才自己试了一下,创建子类去调用函数会重定义,但如果是父类指针指向子类对象,那么不会触发重定义。
直接创建子类对象,会触发重定义,父类被隐藏,如果想使用父类函数,需要 b.A::f(); // 想访问父类方法,只能这样
发表于 2022-10-12 09:23:48 回复(0)
非虚函数指针调用的是声明的类函数,
虚函数指针调用的是指向的类函数。
故:
pObj->Bar((char)(100))(非虚函数),调用Base类(声明的类)intBar(charx)函数,结果是100,
pObj->Bar(100)(虚函数),调用Derived类(指针所指的类)intBar(intx)函数,结果是50.
发表于 2016-05-14 20:28:42 回复(0)
谁家指针就调用谁的成员函数,如果属于虚函数,就会触发动态绑定,指向子类~
发表于 2021-05-10 19:51:55 回复(0)
pobj 是基类的指针,对于虚函数,基类调用虚函数直接调用的是派生类的函数
发表于 2021-02-03 22:07:36 回复(0)
反过来将如果让手撕虚函数应用的代码,这是最典型的代码。 虚函数的调用要看父类指针,父类指针如果指向虚函数则会在子类中寻找实现,担当父类是非虚函数是则调用父类实现
发表于 2019-09-03 00:47:32 回复(0)
答案:B
思路:这道题的选择处可以取巧,用排除法。首先第一个输出指向的是char类型,则我们看上面的bar里的括号类型,只有两个是相配的,那么我们来看一下返回的数值,第一个是本身100,第二个则是-100,而选择处只有两个开头是100的,那么C和D可以排除了。再看第二个数,传递过去的是int类型,相对应的也有两个,那我们来看一下返回的数值,第一个返回200,第二个返回50,AB两个选项的第二个数只存在50,并没有200。所以这道题的正解是B
发表于 2014-12-30 21:41:43 回复(0)
指针定义的类型是父类,指向的类型是子类;虚函数根据指针的指向来选择具体的实现;非虚函数根据指针的类型来选择具体实现
发表于 2022-11-29 11:01:45 回复(0)
我是这样看的,第一个调用Bar函数,形参类型为char型,所以在基类和子类的第一个函数中选择,然后我们基类和子类都没有virtual修饰,这是一种隐藏,所以指针对成员函数的调用取决于指针类型,虽然是指向子类对象,但它是Base类型,所以调用基类的Bar函数。
第二个Bar函数参数是int型,所以在基类和子类第二个函数中选择。而基类Base的该函数有virtual修饰,而子类函数没有virtual修饰,这是一种典型的覆盖(重写)关系,所以调用的是子类的Bar函数。
发表于 2022-10-06 20:55:31 回复(0)
切割与多态。。。。
发表于 2022-08-29 17:54:47 回复(0)
B选项为什么不是-100而是100呢?
发表于 2022-02-25 21:07:16 回复(2)
明确静态绑定和动态绑定的区别,当基类指针指向派生类时会对virtual函数执行动态绑定。
发表于 2022-02-01 11:45:33 回复(0)
B Derived Obj; Base *pObj = &Obj; printf("%d,", pObj->Bar((char)(100))) printf("%d,", pObj->Bar(100)); 第一个Bar(char)是非虚函数,因此是静态绑定,静态绑定是指指针指向声明时的对象,pObj声明时为Base类,因此调用的是Base类的Bar(char) 第二个Bar(char)是虚函数,因此是动态绑定,动态绑定是指指针指向引用的对象,pObj引用Derived对象,因此调用的是Derived类的Bar(int)
发表于 2018-11-26 10:19:25 回复(0)