C++面向对象的抽象 封装继承 多态总结

根源为总结http://www.cnblogs.com/clongge/archive/2008/07/09/1239076.html


面向对象的编程语言不止仅仅多了个类,类可以明显感觉到抽象和封装。抽象的是具体的实现,封装的是接口。

继承,分为实现继承,接口继承,可视化继承。

实现继承就是重新写一个函数去实现。这儿用的是纯虚函数。父辈纯虚,子辈必须重新实现。

接口继承是指纯粹继承父辈的老底,也可以去重新实现。这是虚函数。

可视化继承则是纯粹的全部自己实现,自己功能自己解决。对应的是非虚函数。

继承的时候父子有几种关系,比如B继承A,一种是泛化,换句话就是b是a的一种,比如老师一种人,学生是一种人。杀人犯也是一种人。这叫泛化。这儿可以接口继承或者可视化继承。因为本质是一种的关系么。这儿可以直接用父辈的老底。

在一中是聚合,聚合呢就是b是a的一部分,但是b不是一种a,比如头有眼睛鼻子嘴巴耳朵,这样就要独自去实现。这儿用到的是接口继承和纯虚类。毕竟不能说眼睛是头的一种么,要自己去实现很多的东西。

以上继承的本质是为了更方便的代码复用,而多态则是接口复用。接口复用可以用重载函数来做,也可以用类的多态性来进行。

多态,则更多的是可以用子辈赋给父辈的引用或者指针,然后可以在运行的时候去实现访问子类。这样就看似是一个,还有待补充。慢慢来。看图很不错的。

多态代码

//小结:1、有virtual才可能发生多态现象  
// 2、不发生多态(无virtual)调用就按原类型调用  
#include<iostream>  
using namespace std;  
  
class Base  
{  
public:  
    virtual void f(float x)  
    {  
        cout<<"Base::f(float)"<< x <<endl;  
    }  
    void g(float x)  
    {  
        cout<<"Base::g(float)"<< x <<endl;  
    }  
    void h(float x)  
    {  
        cout<<"Base::h(float)"<< x <<endl;  
    }  
};  
class Derived : public Base  
{  
public:  
    virtual void f(float x)  
    {  
        cout<<"Derived::f(float)"<< x <<endl;   //多态、覆盖  
    }  
    void g(int x)  
    {  
        cout<<"Derived::g(int)"<< x <<endl;     //隐藏  
    }  
    void h(float x)  
    {  
        cout<<"Derived::h(float)"<< x <<endl;   //隐藏  
    }  
};  
int main(void)  
{  
    Derived d;  
    Base *pb = &d;  
    Derived *pd = &d;  
    // Good : behavior depends solely on type of the object  
    pb->f(3.14f);   // Derived::f(float) 3.14  
    pd->f(3.14f);   // Derived::f(float) 3.14  
  
    // Bad : behavior depends on type of the pointer  
    pb->g(3.14f);   // Base::g(float)  3.14  
    pd->g(3.14f);   // Derived::g(int) 3   
  
    // Bad : behavior depends on type of the pointer  
    pb->h(3.14f);   // Base::h(float) 3.14  
    pd->h(3.14f);   // Derived::h(float) 3.14  
    return 0;  
}


令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,但是C++的隐藏规则使问题复杂性陡然增加。
这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
上面的程序中:
(1)函数Derived::f(float)覆盖了Base::f(float)。
(2)函数Derived::g(int)隐藏了Base::g(float),而不是重载。
(3)函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值