注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

又一个部落格

换过很多备忘录,不知道这本怎么样!

 
 
 

日志

 
 

继承,虚函数和多态  

2010-03-02 17:38:29|  分类: c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |



继承
class derived-class : access base-class { // body of derived class }
access 是可选的 ,默认应该是private


#include <iostream>
#include <cstring>
using namespace std;

class TwoDShape{
public:
    double width;
    double height;
    void showDim(){
        cout<<"Width and height are "<<width<<" and "<<height<<endl;
    }
};

//这个地方的public的意思是 父类public的成员,到子类里也是public的
//假如是 protected, 那么原先public和protected 的成员到子类里面会变成protected
//假如是 private, 那么原先public和protected和private的成员到子类里面会变成private
class Triangle :public TwoDShape{
public:
    char style[20];
    double area(){
        return width * height/2;
    }

    void showStyle(){
        cout <<"Triangle is "<<style<<endl;
    }
};

int main() {
    Triangle t1;
    Triangle t2;

    t1.width = 4.0;
    t1.height = 4.0;
    strcpy(t1.style,"isosceles");

    t2.width=8.0;
    t2.height=12.0;
    strcpy(t2.style,"right");

    cout<<"Info for t1:"<<endl;
    t1.showStyle();
    t1.showDim();
    cout<<"Area is "<<t1.area()<<endl;

    cout<<endl;
    cout<<"Info for t2:"<<endl;
    t2.showStyle();
    t2.showDim();
    cout<<"Area is"<<t2.area()<<endl;

    return 0;
}

保护成员在子类中是可以被public和protected继承的子类访问的

构造函数和继承的关系
the constructor for the base class constructs the base class portion of the object,
and the constructor for the derived class constructs the derived class part
意思就是说基类的构造函数构造基类的部分,子类的构造函数构造子类的部分

怎么调用基类的构造函数呢,看下面的例子
#include <iostream>
#include <cstring>
using namespace std;

class TwoDShape{
    double width;
    double height;
public:
    TwoDShape(double w, double h){
        width = w;
        height = h;
    }

    void showDim(){
        cout<<"Width and height are "<<width<<" and "<<height<<endl;
    }
    double getWidth(){
        return width;
    }
    double getHeight(){
        return height;
    }

    void setWidth(double w){
        width = w;
    }
    void setHeight(double h){
        height = h;
    }
};

class Triangle : public TwoDShape{
    char style[20];
public:
    //调用了基类的构造函数
    Triangle(char *str,double w,double h):TwoDShape(w,h){
        strcpy(style,str);
    }

    double area(){
        return getWidth() * getHeight()/2;
    }

    void showStyle(){
        cout <<"Triangle is "<<style<<endl;
    }
};

int main() {
    Triangle t1("isosceles", 4.0,4.0);
    Triangle t2("right", 8.0,12.0);
    cout<<"Info for t1:"<<endl;
    t1.showStyle();
    t1.showDim();
    cout<<"Area is "<<t1.area()<<endl;

    cout<<endl;
    cout<<"Info for t2:"<<endl;
    t2.showStyle();
    t2.showDim();
    cout<<"Area is"<<t2.area()<<endl;

    return 0;
}


假如基类有多个构造函数,那么派生类里面就要写多个构造函数来调用基类的构造函数

继承多个基类
#include <iostream>
using namespace std;
class B1{
protected:
    int x;
public:
    void showx(){
        cout<<x<<endl;
    }
};

class B2{
protected:
    int y;
public:
    void showy(){
        cout<<y<<endl;
    }
};

class D:public B1, public B2{
public:
    void set(int i,int j){
        x=i;
        y=j;
    }
};

int main() {
    D ob;
    ob.set(10,20);
    ob.showx();
    ob.showy();
    return 0;
}

构造函数和析构函数的执行顺序问题
构造函数的顺序是, 先基类,后派生类
析构函数的顺序是, 先派生类,后基类
看下面的程序
#include <iostream>
using namespace std;

class B{
public:
    B(){cout<<"Constructing base protion"<< endl;}
    ~B(){cout<<"Destructing base portion"<<endl;}
};

class D:public B{
public:
    D(){
        cout<<"Constructing derived portion"<<endl;
    }
    ~D(){
        cout<<"Destructing derived portion"<<endl;
    }
};

int main() {
    D ob;

    return 0;
}

输出
Constructing base protion
Constructing derived portion
Destructing derived portion
Destructing base portion

指针与基类,派生类
基类的指针可以指向派生类
B *p;
B B_ob;
D D_ob;
//下面两条语句都是合法的
//但是要注意的是,p指针只能访问 D继承了B的那一部分
//还有一点就是,如果反过来,用派生类指针指向基类,那是不可以的
p=&B_ob;
p=&D_ob;

虚拟函数
虚拟函数什么意思,就是可以被派生类重新定义的函数

#include <iostream>
using namespace std;

class B{
public:
    virtual void who(){
        cout<<"Base"<<endl;
    }
};

class D1:public B{
public:
    void who(){
        cout<<"First derivation"<<endl;
    }
};

class D2:public B{
public:
    void who(){
        cout<<"Second derivation"<<endl;
    }
};

int main() {
    B base_obj;
    B *p;
    D1 D1_obj;
    D2 D2_obj;

    p= &base_obj;
    p->who();

    p= &D1_obj;
    p->who();

    p= &D2_obj;
    p->who();

    return 0;
}

输出为
Base
First derivation
Second derivation


上面的重点是
When a virtual function is called through a base class pointer,
the version of the virtual function actually executed is determined at runtime by the type of object being pointed to.
意思就是,当虚拟函数被一个基类的指针执行的时候,运行时指针指向那个对象类型来决定,而不是指针本身的类型,反过来说,
如果不是虚拟函数,那么上面的输出就是
Base
Base
Base


虚函数看起来很像函数的重载,其实不然.这两个过程是根本不同的.
1.重载函数必须有不同的参数类型,或者不同的参数数量,
  虚拟函数的属性以及参数必须和重新定义的原型必须是完全相同的,如果不一样将丢失虚拟性
2.虚函数必须是一个成员,不能是朋友函数,但是可以是另外一个类的朋友
3.析构函数可以是虚拟的,但构造函数不能

接着看下面
#include <iostream>
using namespace std;

class B{
public:
    virtual void who(){
        cout<<"Base"<<endl;
    }
};

class D1:public B{
public:
    void who(){
        cout<<"First derivation"<<endl;
    }
};

//D2继承D1,但是没有重定义 who 那么 将执行最近的who版本,就是 D1的 who
class D2:public D1{
public:

};

int main() {
    B base_obj;
    B *p;
    D1 D1_obj;
    D2 D2_obj;

    p= &base_obj;
    p->who();

    p= &D1_obj;
    p->who();

    p= &D2_obj;
    D2_obj.who();

    return 0;
}

输出时
Base
First derivation
First derivation

虚拟函数其实最大的用处就是实现类的多态,实现 定义接口和实现 的分类
基类中指定级接口, 然后派生类来实现.

有些时候,我们需要基类只的定义,不实现,派生类必须实现,那么就定义一个纯虚拟函数,
virtual double area()=0;
这样的话,派生类就必须重定义 area函数
假如一个类中有一个纯虚拟的函数,那么我们就认为这个类是抽象类,
一个抽象类不能被用来声明一个对象,但是可以申请该类的指针
  评论这张
 
阅读(155)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017