首页 > 试题广场 >

以下程序的输出是什么?

[单选题]
以下程序的输出是
class Base {
    public:
    Base(int j): i(j)  {}
    virtual~Base() {}
    void func1() {
        i *= 10;
        func2();
    }
    int getValue() {
        return  i;
    }
    protected:
    virtual void func2() {
        i++;
    }
    protected:
    int i;
};
class Child: public Base {
    public:
    Child(int j): Base(j) {}
    void func1() {
        i *= 100;
        func2();
    }
    protected:
    void func2() {
        i += 2;
    }
};
int main() {
    Base * pb = new Child(1);
    pb->func1();
    cout << pb->getValue() << endl; delete pb; } 

  • 11
  • 101
  • 12
  • 102
推荐
Base * pb = new Child(1), 首先创建子类对象,初始化为1;
func1()不是虚函数,所以pb->func1()执行的是基类的func1函数,i= 10,然后调用func2()函数;
这里的func2是虚函数,要往下派生类寻找,找到后执行派生类中的func2(),此时,i = 12;
最后执行pb->getValue(),结果为12
故选C
编辑于 2015-02-03 14:55:51 回复(1)
可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时,  基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,  而不是基类中定义的成员函数(只要派生类改写了该成员函数)。  若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 会调用基类中定义的那个函数。
发表于 2015-04-01 21:06:48 回复(5)
基类的指针指向派生类的对象
基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,而不是基类中定义的成员函数,若不是虚函数,则不管基类指针指向的是哪个派生对象,调用的都是基类中定义的那个函数   
大神解释的真好,谢啦
发表于 2015-12-18 20:33:15 回复(1)
牢记多态发生的三个条件:(1)有继承;(2)虚函数重写;(3)父类指针(引用)指向子类对象。
发表于 2019-06-02 17:40:37 回复(0)
虚函数执行子类,不是虚函数执行基类
发表于 2017-04-11 09:52:56 回复(0)
Base * pb = newChild(1);
pb->func1();
func1()不是虚函数,静态绑定,调用Base::func1();
func2()是虚函数,动态绑定,调用Child::func2();
发表于 2016-01-09 11:14:21 回复(0)
Base * pb = new Child(1);
pb->func1();
func1(),不是虚函数,调用的是基类(Base)的函数,然后调用函数func2();
func2(),是虚函数,调用的是引用派生类(Child)的虚函数;

发表于 2017-03-13 15:45:08 回复(0)
pb是指向基类的指针,基类里面的func1()不是虚函数,所以执行的是i*10,而func2()是一个虚函数,执行的时候动态调用子类的func2(),进行+2操作,最终的结果就是12。
发表于 2021-08-10 17:20:49 回复(0)
没一人觉得这题的参数传递和函数返回值就有问题么?按这样的代码,i不可能等于12的。当然这些小bug相信大家都知道
发表于 2016-10-21 13:19:21 回复(2)
最后少了一个return 0;
发表于 2024-05-06 15:40:31 回复(0)
普通函数,根据指针类型调用。
只有多态(虚函数)的时候,才会根据所指向对象的类型,进行调用。
编辑于 2023-12-18 23:45:41 回复(0)
我怎么记得不加域的话,A类的函数里只会调用A的函数
发表于 2022-04-29 14:26:22 回复(0)
除了虚函数优先调用会调用基类的函数 然后如果是虚函数优先调用有对象的子累
发表于 2021-09-29 08:53:11 回复(0)
func1基类不是虚函数
发表于 2021-06-07 11:44:27 回复(0)
从编译器得到的汇编代码对比虚类函数和一般函数的区别(以gcc 7.5.0为例):
当程序调用pb->func1();并进入Base::func1()函数内时,它调用func2()的汇编语句如下:    
mov rax, QWORD PTR [rbp-8]
mov rax, QWORD PTR [rax]

add rax, 16
mov rdx, QWORD PTR [rax]
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call rdx
而当func2()不是虚函数时,调用func2()的汇编指令如下:
mov     rax, QWORD PTR [rbp-8]
mov     rdi, rax
call    Base::func2()
可以看到,func1()在调用虚函数func2()时,并没有直接调用Base::func2(),而是调整了this指针的位置

生成的汇编文件里还包含Base类和Child类的虚函数表信息:
vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::~Base() [complete object destructor]
.quad Base::~Base() [deleting destructor]
.quad Base::func2()

vtable for Child:
.quad 0
.quad typeinfo for Child
.quad Child::~Child() [complete object destructor]
.quad Child::~Child() [deleting destructor]
.quad Child::func2()
可以确定的是每一个类的func2()的函数地址都在一个槽内,调用func2()的函数实例可以转化为(*pb->vptr[4]) (pb);,最终调用的是哪个类的函数实例需要在执行期才能确定。
编辑于 2021-02-22 16:06:03 回复(0)
基类中的fun1()不是虚函数,所以需要调用基类中的fun1()。基类中的fun2()是虚函数,所以需要调用派生类中的fun2()。
发表于 2020-08-08 15:40:08 回复(0)
有了虚函数这个东西,真是和java不一样啊
发表于 2020-05-06 20:10:32 回复(0)
由于存在虚函数,会发生动态绑定
发表于 2020-02-11 16:43:41 回复(0)
根本还是每个成员函数都有一个this指针
发表于 2019-07-17 12:39:33 回复(0)

这个题func1不是虚函数,而指针是父类指针,所以对这个非虚函数会从父类开始找,因此调用父类func1,func1函数会传一个this指针,this指针调用func2,问题是这个指针为什么是子类的?

发表于 2019-06-26 23:52:56 回复(0)
简单来说就是用派生类对子类复制初始化,会继承使用派生类的虚表
发表于 2017-08-29 00:32:30 回复(0)