注册 登录
编程论坛 C++教室

考考大家对虚函数的理解

yuccn 发布于 2011-03-25 21:53, 1278 次点击
大家先认真想想下面程序输出是什么,再把程序运行一下。
如果答案和你想到的不一样,哪么要认真学习补下基础了。如果和你想到的答案一样,并且明白为什么,哪么你的功底还不错的。^_^
其实题目也很简单,只是大意就很容易出错。(注意,对面向对象理解不够可能导致你做对这题目)
///////////////////////////////////
class Base
{
public:
    Base(){}
    ~Base()
   {
        print();
    }

    virtual void print()
    {
        cout<<"Base - print"<<endl;
    }
};

class Derive : public Base
{
public:
    Derive(){}
    ~Derive(){}
    virtual void print()
   {
        cout<<"Derive - print"<<endl;
    }
};

void OutPrint(Base *pObj)
{
    pObj->print();
}

void main()
{
    Derive Obj;
    OutPrint(&Obj);   
}
////////////////////////////////////
有什么好的题目,希望网友拿出来分享o(∩_∩)o...哈哈


[ 本帖最后由 yuccn 于 2011-3-25 21:55 编辑 ]
15 回复
#2
玩出来的代码2011-03-26 12:04
在原来的基础上改动一下,增加一个知识点、
程序代码:

class Base
{
public:
    Base(){}
    ~Base()
    {
        print();
    }

    virtual void print(int i=1)
    {
        cout<<"Base - print"<<' '<<i<<endl;
    }
};

class Derive : public Base
{
public:
    Derive(){}
    ~Derive(){}
    virtual void print(int i=2)
    {
        cout<<"Derive - print"<<' '<<i<<endl;   
        Base::print(i);
    }
};

void OutPrint(Base *pObj)
{
    pObj->print();
}

void main()
{
    Derive Obj;
    OutPrint(&Obj);
}



[ 本帖最后由 玩出来的代码 于 2011-3-26 12:05 编辑 ]
#3
yuccn2011-03-26 13:04
楼上增加了一个输出,想增加的知识点是什么?
只是在派生类多输出了一条基类的信息,还有时间一个默认参数,没有什么知识点的增加吧。这不属于面向对象的内容。

如果说有知识点的增加,请赐教

[ 本帖最后由 yuccn 于 2011-3-26 13:10 编辑 ]
#4
buffer2011-03-26 16:14
还有一个小知识点
程序代码:
class Base
{
public:
    Base(){}
    ~Base()
    {
        print();
    }

    virtual void print(int i=1)
    {
        cout<<"Base - print"<<' '<<i<<endl;
    }
};

class Derive : public Base
{
public:
    Derive(){}
    ~Derive(){print();}
    virtual void print(int i=2)
    {
        cout<<"Derive - print"<<' '<<i<<endl;   
        Base::print(i);
    }
};

void OutPrint(Base *pObj)
{
    pObj->print();
}

void main()
{
    Derive Obj;
    OutPrint(&Obj);
}
#5
玩出来的代码2011-03-26 16:35
增加输出才能看到效果,只是说明了虚函数的动态绑定与参数的静态绑定。
#6
linzhiqing2011-03-29 08:32
这个知识挺经典的
#7
神左手2011-03-29 20:34
确实要注意基础知识!
#8
yuccn2011-03-29 21:52
应该来总结下帖子了
例子的输出为:
Derive - print
Base - print

第一个输出是 pObj->print();因为虚函数的动态绑定,而调用了派生类的接口。

第二个输出,是在析构基类的时候,或许读者会迷惑,为什么析构基类没有调用了动态绑定的接口。这个就涉及到一个c++的很基础的知识了。因为pObj析构的时候,先是派生类的析构,再到基类的析构。再析构基类的时候,派生类已经析构完成了。故在析构基类的时候还想调用动态绑定的接口是不可以了的(因为派生类已经析构了),故调用了基类的接口。

#9
lixinyuan2242011-04-03 19:24
才学,不懂,观望!大神多啊……
#10
jery24872011-04-06 18:57
第一行是动态联编,第二行是静态联编,析构函数调用虚函数是在编译时确定的,所以要调用基类虚函数而不是派生类的
#11
jery24872011-04-06 19:43
以下是引用yuccn在2011-3-29 21:52:30的发言:

应该来总结下帖子了
例子的输出为:
Derive - print
Base - print

第一个输出是 pObj->print();因为虚函数的动态绑定,而调用了派生类的接口。

第二个输出,是在析构基类的时候,或许读者会迷惑,为什么析构基类没有调用了动态绑定的接口。这个就涉及到一个c++的很基础的知识了。因为pObj析构的时候,先是派生类的析构,再到基类的析构。再析构基类的时候,派生类已经析构完成了。故在析构基类的时候还想调用动态绑定的接口是不可以了的(因为派生类已经析构了),故调用了基类的接口。
我错了,如果是代码~Derive(){}改成~Derive(){ Base *p=new Derive; p->print();delete p; }结果是:  Derive - print
                        Derive - print
                        Base - print
                        Base - print
如果是静态联编,那么第二行应该是Base-print,但实际上是在运行时确定调用派生类虚函数,其实书上所说的构造函数和析构函数调用虚函数是静态联编,不怎么严谨,我想应该是被逼无奈的动态联编,事实上是在运行是确定的,但没办法,对象初始化时,要先初始化基类成员,只能调用基类的虚函数,而当对象销毁时,要先撤销派生类成员的内存空间,所以等到执行基类析构函数,调用虚函数时,只剩下基类的虚函数。要多实践,学习!
#12
weststreet2011-04-07 13:25
Derive-print
#13
wkhs1982011-04-07 19:46
请问第一次执行     pObj->print();时,为什么没使用 Derive中print(int i = 2)中的i值 而确是 Base中的i值
#14
wkhs1982011-04-07 19:51
调试后的结果为 :   Derive - print 1
                    Base - print 1
                    Derive - print 2
                    Base - print 2
                    Base - print 1
为何 第一次  调用pObj->print()的时候 未使用Derive中的print(int i = 2)中默认值?却使用了Base中的print(int i =1)中的i值?
#15
myseemylife2011-04-24 22:25
void OutPrint(Base *pObj)
{
    pObj->print();
}

void main()
{
    Derive Obj;
    OutPrint(&Obj);   
}
这里 &obj是一个Derive类型的,函数参数是base*类型的,这之间是怎么转换的,进入print这个函数后。pObj是base*,还是Derive*,
 有这个过程么?pobj = (Base *)(&obj),
#16
哈利波特隐2011-04-25 23:56
都搞不懂啊,刚来,希望能在这取到经
1