zoukankan      html  css  js  c++  java
  • 22.C++- 继承与组合,protected访问级别

    在C++里,通过继承和组合实现了代码复用,使得开发效率提高,并且能够通过代码看到事物的关系

    组合比继承简单,所以在写代码时先考虑能否组合,再来考虑继承.


    组合的特点

    • 其它类的对象作为当前类的成员使用

    比如主机类,拥有 CPU/主板/内存/硬盘这4个对象成员,而这4个对象成员并没有继承主机类的特性和行为

    继承的特点

    • 新的类(子类)具有旧的类(父类)的属性和行为
    • 旧的类被称为父类,也叫基类
    • 新的类被称为子类,也叫派生类(一个派生类也可以继承多个基类)
    • 子类可以添加新的属性和行为(成员变量和成员函数),也可以重写已有的属性和行为
    • 一个子类只继承一个父类,便被称为单继承
    • 一个子类若继承多个父类,便被称为多继承
    • 子类其实就是一个特殊的父类,比如:苹果手机是手机,就是将苹果手机当做一个特殊的父类对待

    子类对象可以初始化父类对象,也可以赋值给父类对象,比如:

    class Parent
    {
           int mValue;
    public:    
           Parent()
           {
                  mValue=10;
           }  
           int Value()
           {
                  return mValue;
           } 
    };
    
    class Child : public Parent
    {
    public:    
            Child()
           {
                  cout<<"I'm child"<<endl;
           }
    };
    
    int main()
    {
           Child c;
    cout
    << c.Value() <<endl; //调用父类的成员函数 Parent p1 =c;    //通过子类初始化父类 Parent p2; p2=c; //通过子类复制给父类 }

    类的访问级别之protected

    大家都知道,类里private修饰的成员和函数,不能被外界直接访问.

    虽然子类拥有父类的属性和行为,但是在子类里,也不能访问父类的private私有成员

    比如:

    class Parent
    {
           int mValue;
    public:    
           Parent(int i=0)
           {
                  mValue=i;
           }
           int Value()
           {
                  return mValue;
           } 
    };
    
    class Child : public Parent
    {
    public:    
            Child()
           {
              cout<<mValue<<endl;         //在子类中,访问父类的private成员,将会编译报错
           }
    };

    所以类的访问级别引入了新的关键字protected

    protected的特性

    • 修饰的成员不能被外界直接访问
    • 修饰的成员可以被子类(包括子类的子类)直接访问, 也可以在本类内部直接访问

    有了protected的加入,定义类时,我们就需要仔细考虑成员的访问级别,如下图所示:

     

    接下来做个综合实例,组合与继承

    • 需要一个父类Object, 为子类Point子类Line 提供name名字和info信息
    • 由于线Line至少需要两个点Point才能组成,所以Line子类内部需要通过Point子类来组合

    如下图所示:

     

    开始写代码:

    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    class Object
    {
    protected:
           string mName;
           string mInfo;
    public:
            Object()
           {
                  mName="Object";
                  mInfo="";             
           }
           string name()
           {
                  return mName;
           }
           string info()
           {
                  return mInfo;
           }
    };
    
    class Point      : public Object
    {
    protected:
           int x;                     //坐标
           int y;
    
    public:
           Point(int x=0,int y=0)
           {
                  ostringstream s;
                  this->x =x;
                  this->y =y;
                  s<<"P("<<x<<","<<y<<")";  //坐标信息
                  mName="Point";
                  mInfo=s.str();
           } 
    };
    
    class Line : public Object
    {
    private:
           Point mP1;
           Point mP2;
    public:
           Line(Point p1,Point p2)
           {
                  ostringstream s;
                  mP1 =p1;
                  mP2 =p2;
                  s<<"Line from " <<p1.info() <<" to "<<p2.info();      //线的信息
                  mName ="Line";
                  mInfo =s.str();
           }
    };
    
    int main()
    {
           Point p1(2,3); 
           Point p2(6,3);
           Line  L(p1,p2);
    /*打印点的信息*/ cout<<p1.name()<<":"<<endl; cout<<p1.info()<<endl; /*打印线的信息*/ cout<<L.name()<<":"<<endl; cout<<L.info()<<endl; return 0; }

    运行打印:

    Point:
    P(2,3)
    
    Line:
    Line from P(2,3) to P(6,3)

    接下来来学习: 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、虚函数

  • 相关阅读:
    tcp没用吗?为什么MOBA、“吃鸡”游戏不推荐用tcp协议
    这样做动画交互,一点都不费力!
    sql server 小记——分区表(上)
    vs中不得不会的一些小技巧(1)——细说查找
    Aforge.net之旅——开篇:从识别验证码开始
    Redis Hash操作
    Varint 数值压缩
    LevelDB Version
    LevelDB Cache机制
    LevelDB Compaction操作
  • 原文地址:https://www.cnblogs.com/lifexy/p/8698104.html
Copyright © 2011-2022 走看看