继承

作者: 85dc0dea73fd | 来源:发表于2019-02-25 14:32 被阅读0次

title: c++之继承
tags:


继承

C++派生语法

class Base
{
// ... base class members
};
class Derived: access-specifier Base
{
// ... derived class members
};
其中 access-specifier 可以是 public(这是最常见的,表示派生类是一个基类)、private 或 protected

下面是一个简单的历程,用来加深对继承的理解。

鱼类世界呈现的一种简单的继承层次结构

 #include <iostream> 
using namespace std; 
class Fish 
{ 
public: 
bool isFreshWaterFish; 
void Swim() 
{ 
if (isFreshWaterFish) 
cout << "Swims in lake" << endl; 
else 
cout << "Swims in sea" << endl; 
} 
}; 

class Tuna: public Fish 
{ 
public: 
Tuna() 
{ 
isFreshWaterFish = false;
} 
}; 

class Carp: public Fish 
{ 
public: 
Carp() 
{ 
isFreshWaterFish = true; 
} 
}; 

int main() 
{ 
Carp myLunch; 
Tuna myDinner; 

cout << "About my food:" << endl; 

cout << "Lunch: "; 
myLunch.Swim(); 

cout << "Dinner: "; 
myDinner.Swim(); 

return 0; 
} 
输出:
About my food: 
Lunch: Swims in lake 
Dinner: Swims in sea

访问限定符 protected

public 和 private 一样,protected 也是一个访问限定符。将属性声明为 protected 的时,
相当于允许派生类和友元类访问它,但禁止在继承层次结构外部(包括 main( ))访问它.

一种更好的 Fish 类设计,它使用关键字 protected 将成员属性只暴露给派生类
#include <iostream> 
 using namespace std; 

class Fish 
   { 
    protected: 
       bool isFreshWaterFish;  
    public: 
         void Swim() 
   { 
      if (isFreshWaterFish) 
     cout << "Swims in lake" << endl; 
   else 
      cout << "Swims in sea" << endl; 
 } 
    }; 

 class Tuna: public Fish
  { 
public: 
    Tuna() 
      { 
 isFreshWaterFish = false; // set protected member in base 
     }
  }; 

class Carp: public Fish 
 { 
public: 
    Carp() 
   { 
  isFreshWaterFish = false; 
   } 
 }; 

int main() 
{
 Carp myLunch; 
 Tuna myDinner; 
 cout << "About my food" << endl;  
 cout << "Lunch: "; 
 myLunch.Swim();  
 cout << "Dinner: "; 
 myDinner.Swim(); 
 return 0; 
    } 
}

输出:
About my food 
Lunch: Swims in lake 
Dinner: Swims in sea 


## 基类初始化—向基类传递参数
 结构如下:
class Base 
{ 
public: 
 Base(int someNumber) // overloaded constructor 
 { 
 // Use someNumber 
 } 
}; 
Class Derived: public Base 
{ 
public: 
 Derived(): Base(25) // instantiate Base with argument 25 
 { 
 // derived class constructor code 
 } 
}; 

下面看一下具体例子;

#include <iostream> 
  using namespace std;  
 class Fish 
     { 
  protected: 
           bool isFreshWaterFish; // accessible only to derived classes 
 public: 
          Fish(bool isFreshWater) : isFreshWaterFish(isFreshWater)
         {
         } 
 void Swim() 
     { 
      if (isFreshWaterFish) 
         cout << "Swims in lake" << endl; 
   else 
         cout << "Swims in sea" << endl; 
    } 
  }; 

class Tuna: public Fish 
 { 
 public: 
        Tuna(): Fish(false) 
          {
           }
 }; 

class Carp: public Fish 
 { 
public: 
         Carp(): Fish(true)
          {
          } 
  }; 
 
 int main() 
 { 
       Carp myLunch; 
       Tuna myDinner; 
 cout << "About my food" << endl; 
cout << "Lunch: "; 
 myLunch.Swim(); 
cout << "Dinner: "; 
myDinner.Swim(); 
 return 0; 
} 

输出:
About my food 
Lunch: Swims in lake 
Dinner: Swims in sea

在派生类中覆盖基类的方法

如果派生类实现了从基类继承的函数,且返回值和特征标相同,就相当于覆盖了基类的这个方法,
如下面的代码所示:
class Base
{
public:
void DoSomething()
{
// implementation code… Does something
}
};
class Derived:public Base
{
public:
void DoSomething()
{
// implementation code… Does something else
}
};

派生类 Tuna 和 Carp 覆盖了基类 Fish 的方法 Swim( ) 
 #include <iostream> 
using namespace std; 

class Fish 
        { 
private: 
        bool isFreshWaterFish; 
 public: 
        Fish(bool isFreshWater) 
         : isFreshWaterFish(isFreshWater)
          {
          } 
 void Swim() 
 { 
if (isFreshWaterFish) 
 cout << "Swims in lake" << endl; 
       else 
 cout << "Swims in sea" << endl; 
 } 
          }; 

 class Tuna: public Fish 
 { 
public: 
       Tuna()
         : Fish(false) 
{
} 
 void Swim() 
{ 
 cout << "Tuna swims real fast" << endl; 
   } 
    }; 

 class Carp: public Fish 
{ 
 public: 
        Carp()
              : Fish(true)
              {
              } 
 void Swim() 
  { 
      cout << "Carp swims real slow" << endl; 
   } 
 }; 

int main() 
 { 
Carp myLunch; 
Tuna myDinner; 
cout << "About my food" << endl; 
cout << "Lunch: "; 
myLunch.Swim(); 
cout << "Dinner: "; 
 myDinner.Swim(); 
return 0; 
 } 

输出:
About my food 
Lunch: Carp swims real slow 
Dinner: Tuna swims real fast 

分析: myLunch.Swim( )调用的是 Carp::Swim( )。同样,myDinner.Swim( )调用的是Tuna::Swim( )。换句话说,基类 Fish 中 Swim( )被派生类 Tuna 和 Carp 类中的 Swim( )覆盖了。要调用 Fish::Swim( ),只能在 main( )中使用作用域解析运算符显式地调用它。
即:如果要在 main( )中调用 Fish::Swim( ),需要使用作用域解析运算符(::),如
下所示:
myDinner.Fish::Swim();

在派生类中调用基类的方法

如果要在 Tuna::Swim( )
和 Carp::Swim( )的实现中重用 Fish::Swim( )的通用实现,可使用作用域解析运算符(::),如下面的代
码所示:
class Carp: public Fish
{
public:
Carp(): Fish(true) {}
void Swim()
{
cout << "Carp swims real slow" << endl;
Fish::Swim(); // invoke base class function using operator::
}
};

具体应用

在基类方法和 main( )中,使用作用域解析运算符(::)来调用基类方法

 #include <iostream> 
using namespace std; 
 class Fish 
{ 
 private: 
 bool isFreshWaterFish;  
public: 
 Fish(bool isFreshWater) : isFreshWaterFish(isFreshWater){} 
void Swim() 
{ 
 if (isFreshWaterFish) 
 cout << "Swims in lake" << endl; 
 else 
cout << "Swims in sea" << endl; 
 } 
 }; 
 class Tuna: public Fish 
 { 
 public: 
 Tuna(): Fish(false) {} 
 void Swim() 
 { 
 cout << "Tuna swims real fast" << endl; 
 } 
 }; 
 class Carp: public Fish 
 { 
 public: 
 Carp(): Fish(true) {} 
 void Swim() 
 { 
 cout << "Carp swims real slow" << endl; 
Fish::Swim(); 
 } 
 }; 
 int main() 
 { 
Carp myLunch; 
 Tuna myDinner; 
 cout << "About my food" << endl;  
 cout << "Lunch: "; 
 myLunch.Swim(); 
 cout << "Dinner: "; 
 myDinner.Fish::Swim(); 
 return 0; 
 } 
输出:
About my food 
Lunch: Carp swims real slow 
Swims in lake 
Dinner: Swims in sea 

构造顺序

基类对象在派生类对象之前被实例化。首先构造 Tuna 对象的Fish 部分,这样实例化 Tuna 部分时,成员属性(具体地说是 Fish 的保护和公有属性)已准备就绪,可以使用了。实例化 Fish 部分和 Tuna 部分时,先实例化成员属性(如 Fish::isFreshWaterFish),再调用构造函数,确保成员属性准备就绪,可供构造函数使用。这也适用于 Tuna::Tuna( )。
析构顺序与此相反

私有继承

格式如下:
class Base
{
// ... base class members and methods
};
class Derived: private Base // private inheritance
{
// ... derived class members and methods
};

私有继承意味着在派生类的实例中,基类的所有公有成员和方法都是私有的—不能从外部访问。
换句话说,即便是 Base 类的公有成员和方法,也只能被 Derived 类使用,而无法通过 Derived 实例来
使用它们。
在公有继承中,,可在 main( )中通过 Tuna 实例调用 Fish::Swim( ),因为 Fish::Swim( )是个公有方法,且 Tuna 类是以公有方式从 Fish 类派生而来的。而在私有继承中无法实现。私有继承使得只有子类才能使用基类的属性和方法,因此也被称为 has-a 关系。
比如由发动机派生汽车,由小到大的派生。

实例

Car 类以私有方式继承 Motor 类
 0: #include <iostream> 
 using namespace std; 
 class Motor 
 { 
 public: 
 void SwitchIgnition() 
   { 
 cout << "Ignition ON" << endl; 
  } 
 void PumpFuel() 
   { 
 cout << "Fuel in cylinders" << endl; 
   } 
 void FireCylinders() 
 { 
 cout << "Vroooom" << endl; 
 } 
           };  

class Car:private Motor // private inheritance 
 { 
 public: 
 void Move() 
{ 
   SwitchIgnition(); 
   PumpFuel(); 
   FireCylinders(); 
    } 
           }; 

 int main() 
 { 
    Car myDreamCar; 
    myDreamCar.Move(); 
 return 0; 
 } 

输出:
Ignition ON 
Fuel in cylinders 
Vroooom 

保护继承

结构如下:
class Base
{
// ... base class members and methods
};
class Derived: protected Base // protected inheritance
{
// ... derived class members and methods
};
特征:
• 它也表示 has-a 关系;
• 它也让派生类能够访问基类的所有公有和保护成员;
• 在继承层次结构外面,也不能通过派生类实例访问基类的公有成员。
随着继承层次结构的加深,保护继承将与私有继承有些不同:
class Derived2: protected Derived
{
// can access public & protected members of Base
}
在保护继承层次结构中,子类的子类(即 Derived2)能够访问 Base 类的公有和保护成员

实例理解

 RaceCar 类以保护方式继承了 Car 类,而 Car 类以保护方式继承了 Motor 类
#include <iostream> 
 using namespace std; 
 class Motor 
 { 
 public: 
 void SwitchIgnition() 
 { 
 cout << "Ignition ON" << endl; 
 } 
void PumpFuel() 
 { 
 cout << "Fuel in cylinders" << endl; 
 } 
void FireCylinders() 
 { 
cout << "Vroooom" << endl; 
 } 
 }; 
 class Car:protected Motor 
{ 
public: 
 void Move() 
 { 
 SwitchIgnition(); 
PumpFuel(); 
FireCylinders(); 
 } 
 };  
class RaceCar:protected Car 
 { 
public: 
 void Move() 
 { 
SwitchIgnition(); 
 PumpFuel(); 
 FireCylinders();
 FireCylinders(); 
 FireCylinders(); 
 } 
 }; 
 int main() 
 { 
 RaceCar myDreamCar;
 myDreamCar.Move();  
return 0; 
 } 

输出:
Ignition ON 
Fuel in cylinders 
Vroooom 
Vroooom 
Vroooom 

多继承

class Derived: access-specifier Base1, access-specifier Base2
{
// class members
};

使用 final 禁止继承

被声明为 final 的类不能用作基类。


文章依据21天学通C++第八版,纯属小白自学!!!!

相关文章

  • 继承 继承

    属性拷贝 继承不单单能通过原型链实现,也能通过其他方式实现,属性拷贝就是其中一种方法。 通过属性拷贝也能实现继承子...

  • 继承(单继承,多继承)

    将共性的内容放在父类中,子类只需要关注自己特有的内容 python中所有的内容都是对象,所有的对象都直接或间接继承...

  • js继承方式

    类式继承 构造函数继承 组合继承 类式继承 + 构造函数继承 原型式继承 寄生式继承 寄生组合式继承 寄生式继承 ...

  • Python-学习之路-08 OOP -02

    单继承和多继承 单继承:每个类只能继承一个类 多继承:每个类可以继承多个类 单继承的多继承的优缺点 菱形继承/钻石...

  • 原型相关(二)

    1.继承 继承方式:接口继承(只继承方法签名)实现继承(继承实际的方法)ECMAScript只支持实现继承,并且主...

  • 继承

    继承的引入和概述 继承案例和继承的好处 继承的弊端 Java中继承的特点 继承的注意实现和什么时候使用继承 继承中...

  • Java面向对象三大特性之继承

    继承 一、继承的特点 Java只支持单继承单继承 多继承 单继承、多继承优缺点①单继承优点:提高了代码的复用性,让...

  • 7、面向对象的程序设计3(《JS高级》笔记)

    三、继承 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际方法。由...

  • 【重学前端】JavaScript中的继承

    JavaScript中继承主要分为六种:类式继承(原型链继承)、构造函数继承、组合继承、原型式继承、寄生式继承、寄...

  • js之继承

    文章主讲 JS 继承,包括原型链继承、构造函数继承、组合继承、寄生组合继承、原型式继承、 ES6 继承,以及 多继...

网友评论

      本文标题:继承

      本文链接:https://www.haomeiwen.com/subject/rrdvyqtx.html