title: c++之继承
tags:
- 语言工具
- c++
categories: c++
date: 2019-02-22
thumbnail: https://upload-images.jianshu.io/upload_images/16271012-b9d61cc2379c189c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
继承
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++第八版,纯属小白自学!!!!