C++面试题

挣扎中前行 2013-05-25 06:45:45
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(void)
{
Base *pb = new Child(1);
pb->func1();
cout<<pb->getValue()<<endl;
delete pb;

return 0;
}


结果是12,但为啥等于12不是很明了,望高手详细解释下!
...全文
602 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
我看你有戏 2013-05-27
  • 打赏
  • 举报
回复
引用 23 楼 ananluowei 的回复:
没有virtual,指针是什么类型就执行那个类型的函数, 有virtual,指针所指的对象是什么类型就转去执行对象的函数,而不执行指针的类型的函数。
很精辟
大尾巴猫 2013-05-27
  • 打赏
  • 举报
回复
没有virtual,指针是什么类型就执行那个类型的函数, 有virtual,指针所指的对象是什么类型就转去执行对象的函数,而不执行指针的类型的函数。
blackkettle 2013-05-27
  • 打赏
  • 举报
回复
ochonglangzheo 2013-05-27
  • 打赏
  • 举报
回复
你分别在两个类的func1和func2中加写log,然后运行下,就会知道其中原理
有新工作否 2013-05-27
  • 打赏
  • 举报
回复
引用 16 楼 luoxuechengbing 的回复:
[quote=引用 14 楼 mujiok2003 的回复:] [quote=引用 13 楼 luoxuechengbing 的回复:] [quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?[/quote] 看看这篇文章,网上有很多讲解。 不是链表,一般叫虚函数表, 但这不属于C++标准。 [/quote] 人笨,所以开窍慢,还望多提示点。[/quote] 这么多人,没有几个人把话说清楚的。 1、在堆上建一个child对象,对象的i = 1;指针pb为Base类型; 2、pb调用func1,func1不是虚函数,在这时候就要静态编译的。这时候是一个关键点,pb指向child对象的基类部分,即base::func1。 pb是无法调用child对象中,除基类部分的其余部分的。就是pb是无法调用child::func1的。 这并不是什么覆盖不覆盖的问题,覆盖只是表面。 3、进入func1函数,执行第一句,没有问题;第二句是关键点,根据答案,大家都知道,这是调用的child的func2,但是为什么调用。 刚才说了,pb是无法调用child对象中,除基类部分的其余部分的。那你怎么还说调用child中的func2了呢?其实就是关键字virtual,这个关键字不但把base::func2和child::func2两个函数"糅合"在一起,还把这个函数可以被一条“链”上的对象“共享”,即父对象和子对象都能调用。 在运行的时候,根据实际对象的类型,判断使用哪一个函数。 有如下伪代码; if(*this == Base) Base::func2; if(*this == Child) Child::func2; .....
sniffer12345 2013-05-27
  • 打赏
  • 举报
回复
都怪C++ 搞得这么不清不楚 事实上对于 pb->func1();是什么呢? 你可以想象成c_func1(pb) 就是把实例指针传进去作为参数运算。 第一个函数func1由于不是虚函数,那么根据pb是Base*,那么就调用Base的fun1的 但是在func1()中调用func2(),实际上是什么呢?实际上是this->func2(),也即是c_func2(this),即c_func2(pb) func2是虚函数,那么pb虽然是Base*,但实际上他的值是一个Child实例的地址,那么根据他的虚函数表,找出来的就是child的func2
guo1018902817 2013-05-27
  • 打赏
  • 举报
回复
就因为他new的是自类对象 当然先从子类 找函数 找不到再去基类
笑缘心归ylm 2013-05-27
  • 打赏
  • 举报
回复
今天刚遇到这个问题,来这就看到了
liuduo251 2013-05-26
  • 打赏
  • 举报
回复
受教了,学习了一下
引用 14 楼 mujiok2003 的回复:
[quote=引用 13 楼 luoxuechengbing 的回复:] [quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?[/quote] 看看这篇文章,网上有很多讲解。 不是链表,一般叫虚函数表, 但这不属于C++标准。 [/quote]
zybjtu 2013-05-26
  • 打赏
  • 举报
回复
普通的函数调用使用早捆绑,virtual函数使用晚捆绑。这就是原因。
我看你有戏 2013-05-26
  • 打赏
  • 举报
回复
pb->func1(); 主要是这里,先调用了Base::func1(),然后,在这里有个fun2虚函数,调用的是Child::func2 lz主要还是没有了解函数覆盖和虚函数吧
SKATE11 2013-05-26
  • 打赏
  • 举报
回复
引用 3 楼 zhenwo123 的回复:
[quote=引用 1 楼 mujiok2003 的回复:]

    void Base::func1()
    {
        //i = 1
        i *= 10;
        //i = 10 
        func2();//调用Child::func2()
    }
    
    void Child::func2()
    {
       //i = 10
         i += 2;
      // i = 12
    }

关键是这一句Base *pb = new Child(1);产生的派生类对象赋值给了基类指针,这个基类指针会调用派生类里的函数吗?这算不算运行时多态啊?[/quote]这就是多态啊
  • 打赏
  • 举报
回复
引用 14 楼 mujiok2003 的回复:
[quote=引用 13 楼 luoxuechengbing 的回复:] [quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?[/quote] 看看这篇文章,网上有很多讲解。 不是链表,一般叫虚函数表, 但这不属于C++标准。 [/quote] 人笨,所以开窍慢,还望多提示点。
  • 打赏
  • 举报
回复
引用 14 楼 mujiok2003 的回复:
[quote=引用 13 楼 luoxuechengbing 的回复:] [quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?[/quote] 看看这篇文章,网上有很多讲解。 不是链表,一般叫虚函数表, 但这不属于C++标准。 [/quote] 好东西!!!!!!但是我还是不懂,如楼主提出的问题,为什么没有调用 基类的virtual fun2();而是跑到派生类中去调用 fun2();
mujiok2003 2013-05-26
  • 打赏
  • 举报
回复
引用 13 楼 luoxuechengbing 的回复:
[quote=引用 12 楼 mujiok2003 的回复:] [quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?[/quote] 看看这篇文章,网上有很多讲解。 不是链表,一般叫虚函数表, 但这不属于C++标准。
  • 打赏
  • 举报
回复
引用 12 楼 mujiok2003 的回复:
[quote=引用 11 楼 luoxuechengbing 的回复:] [quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。 [/quote] 声明为 虚函数,编译器会自动帮我们插入一个 链表,但是这个链表我不太清楚,他是怎么弄的? 可以解答一下吗?
mujiok2003 2013-05-26
  • 打赏
  • 举报
回复
引用 11 楼 luoxuechengbing 的回复:
[quote=引用 10 楼 hugett 的回复:] func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?[/quote] 不是“优先”, 该调用哪个就是那个,请区别覆盖和隐藏。
  • 打赏
  • 举报
回复
引用 10 楼 hugett 的回复:
func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
是不是说, 优先调用 非虚函数?
hugett 2013-05-26
  • 打赏
  • 举报
回复
func1不是虚函数。。调用Base版本。。func2是虚函数。。调用Child版本。。 所以先i*=10再i+=2,结果为12。。
diaolingle 2013-05-26
  • 打赏
  • 举报
回复
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base
{
public:
    Base(int j) : i(j) {  } 
    virtual ~Base() {  }
    virtual 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(void)
{
    Base *pb = new Child(1);
    pb->func1();
    cout<<pb->getValue()<<endl;
    delete pb;
     
    return 0;
}
这样就等于102. 原题中基类的func1()没有定义为虚函数,所以pb->func1()调用的是base版本的,所以此时i=10,然后在func1()中调用的func2()基类中已声明为虚函数,调用时发生动态绑定,使其调用的是派生类版本,所以i=12.
加载更多回复(8)

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧