龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > VC开发 >

接触VC之二:MFC类基础,C++程序编写规范介绍(2)

时间:2009-12-30 15:42来源:未知 作者:admin 点击:
分享到:
二、类的继承 接着,要来说说类的继承。 再拿鸟类来举例子吧。鸟类还可以细分成很多类,鸡啊,鸵鸟啦,什么的。它们都是鸟类,在整体上有着共同的

二、类的继承

接着,要来说说类的继承。 再拿鸟类来举例子吧。鸟类还可以细分成很多类,鸡啊,鸵鸟啦,什么的。它们都是鸟类,在整体上有着共同的特征和行为,但也有其它不同点。C++类中也会存在相似的地方。怎么办?重新再写一个类,重新再写那些相同的成员吗?这时就需要继承了。我们可以写这样一个类:

class Ostrich : public Aves{}继承的写法为:

class 派生类名 : 权限关键字(在VC中一般为public) 基类名<,基类名2<…,基类名n>>

这个Ostrich类继承于Aves类,Ostrich类现在就拥有Aves类中所有的成员。如果从Ostrich类声明一对象aOstrich,就可以直接调用其aOstrich.run()。实际上就是在调用Aves类中run成员函数。现在要是在Ostrich类上添加成员的话,就是在Aves类的基础上添加成员。需要说的,在Aves类中有一个私有成员m_strBowels。因为其是私有成员,所以对于其派生类Ostrich也是不可见的。为了解决这个问题,需要将Aves类中的private关键字改为protected关键字。将m_strBowels成员描述为保护型。保护型,对其派生类是可见,对于外部和私有一样是不可见的。在现实中,鸵鸟是不会飞的,叫声也不一样,那么我们就需要更改其行为。代码如下:

class Ostrich : public Aves{public:    void tweet();    void fly();}void Ostrich::tweet(){   

out<<"gugugugugugugu"<<endl;}void Ostrich::fly(){    cout<<"I can''t fly by "<<m_strWing<<endl;}我们在Ostrich类的基础写了fly(),tweet()成员函数,这是与基类的成员函数名字相同。那么它们将覆盖基类的函数,如果再调用Ostrich类的fly(),tweet()函数的话则会调用我们新写的这两个函数了。基本代码如下:

#include <iostream.h>#include <string.h>class Aves{   public:    Aves ();    ~Aves ();    void tweet();    void run();    void fly();    char m_strHead[10];    char m_strTrunk[10];    char m_strCrura[10];    char m_strWing[10];protected:    char m_strBowels[10];}; Aves::Aves(){    strcpy(m_strHead, "Head");    strcpy(m_strTrunk, "Trunk");    strcpy(m_strCrura, "Crura");    strcpy(m_strWing, "Wing");    strcpy(m_strBowels, "Bowels");    cout<<"a bird born!"<<endl;}Aves::~Aves(){    cout<<"a bird die!"<<endl;}void Aves::tweet(){    cout<<"jijijijijijiji"<<endl;}void Aves::run(){    cout<<"I can run by "<<m_strCrura<<endl;}void Aves::fly(){    cout<<"I can fly by "<<m_strWing<<endl;}class Ostrich : public Aves{public:    void tweet();    void fly();};void Ostrich::tweet(){    cout<<"gugugugugugugu"<<endl;}void Ostrich::fly(){    cout<<"I can''t fly by "<<m_strWing<<endl;}void main(){    {         Aves bird;         bird.fly();         bird.run();         bird.tweet();    }    cout <<"====================="<<endl;    {         Ostrich aOstrich;         aOstrich.fly();         aOstrich.run();         aOstrich.tweet();    }}在主函数中我加多加了两对大括号,请大家分析一下bird,aOstrich生存区域。   以上是一个单继承的例子,至于多继承解释理论是一样。大家可以自己尝试。在后的第七部分中的COM编写中将出现多继承的现象。 在继承派生还记得,派生类对象也是其基类的对象,基类的指针是可以指向派生类的对象的。如我们有是一个Aves *lpBird;指针,那么我们写lpBird=&aOstrich是合法的,因为鸵鸟也是一种鸟。 现在,要提到类最后的一个重要概念就是虚成员函数。

  三、虚函数

  上一段文字里说到一个基类指针可以指向一个派生类的对象。如果当lpBird指向了aOstrich,那么调用lpBird->fly();的结果会是什么呢?哇,是”I can fly by Wing”,快来看呐,我们指的那只鸟居然会飞了!显然这是我们不希望看到的结果。为了解决这个问题,我在Aves类声明体中将所有成员函数定义为virtual虚函数。

class Aves{   public:    Aves ();    ~Aves ();    virtual void tweet();    virtual void run();    virtual void fly();    char m_strHead[10];    char m_strTrunk[10];    char m_strCrura[10];    char m_strWing[10];protected:    char m_strBowels[10];};再试试看,结果成为我们要的” I can’t fly by Wing”了。为什么呢?是这样的。当一个类中有虚函数(包括基类含有的)的时候,会给这个类的所有虚函数建立起一个表,函数名与函数地址的映射(包括基类的虚函数)。当对象执行一个虚函数时,则系统先会查这个虚函数表(vtable),找到这个函数名对应的函数地址,调用它。当在派生类添加了与基类虚函数同名的函数,系统会自动将其设定为虚函数。并将这个函数地址改写到虚函数表中。如果再调用这个虚函数时,就会调用新添加的虚函数。像上面的例子,当调用lpBird->fly()时,系统会先查lpBird指向对象的虚函数表,而不会不管三七二十一地直接调用其本类的函数。示例代码如下:

收藏文章
表情删除后不可恢复,是否删除
取消
确定
图片正在上传,请稍后...
评论内容为空!
还没有评论,快来抢沙发吧!
按钮 内容不能为空!
立刻说两句吧! 查看0条评论
精彩图集

赞助商链接