您的位置:首页 > 编程语言 > C语言/C++

《C++大学教程》学习笔记(十一)

2018-02-16 22:11 405 查看

《C++大学教程》学习笔记(十一)

1.继承

1.1实例

本章的内容不多,主要讨论的是面向对象编程(OOP)的另外一个关键特征:继承(inheritance)。继承是软件复用的一种方式,其中新类(“派生类”)吸收了现有类(“基类”)的数据和行为,并使这些类具有其他的新性能。

由于书中的给出的实例实在是太为复杂,所以我自己捣鼓了一个实现继承的样例:基类为交通工具Vehicle,派生类为Car,我们先定义一个Vehicle类,再用后定义的Car类去public继承它。

下面给出实例的文件结构与具体代码:



Vehicle.hpp文件:

#ifndef Vehicle_hpp
#define Vehicle_hpp

#include <string>
#include <iostream>
#include <stdexcept>
using namespace std;

class Vehicle{

private:
string brand;             //品牌
int topSpeed;             //最高速度

public:
Vehicle(string,int);

void setBrand(string);
string getBrand() const;

void setTopSpeed(int);
int getTopSpeed() const;
};

#endif /* Vehicle_hpp */


Vehicle.cpp文件:

#include "Vehicle.hpp"

Vehicle::Vehicle(string b,int ts)
:brand(b),topSpeed(ts)
{
//Nothing
}

void Vehicle::setBrand(string b){
brand = b;
}

string Vehicle::getBrand() const{
return brand;
}

void Vehicle::setTopSpeed(int ts){
if (ts > 0)
topSpeed = ts;
else
throw invalid_argument("TopSpeed must > 0");
}

int Vehicle::getTopSpeed() const {
return topSpeed;
}


Car.hpp文件:

#ifndef Car_hpp
#define Car_hpp

#include "Vehicle.hpp"

//派生类Car通过public方式继承基类Vehicle
class Car : public Vehicle{
private:
int seats;              //座位数

public:
Car(string,int,int);
void setSeats(int);
int getSeats() const;
void print() const;
};

#endif /* Car_hpp */


Car.cpp文件:

#include "Car.hpp"

//这里先直接调用基类的构造函数初始化基类的数据成员,再进行后续操作
Car::Car(string b,int ts,int s)
: Vehicle(b,ts)
{
setSeats(s);
}

void Car::setSeats(int s){
if (s > 0)
seats = s;
else
throw invalid_argument("seats must > 0");
}

int Car::getSeats() const{
return seats;
}

void Car::print() const{
cout << "Brand:" << getBrand() << " TopSpeed:" << getTopSpeed() << " Seats:" << seats << endl;
//在派生类中,无法直接访问基类的private成员,但可以通过调用基类的public成员函数来间接访问
}


main.cpp文件:

#include "Car.hpp"
#include <iostream>
using namespace std;

int main(){

Car car1("BMW",200,5);
Car car2("Ferrari",350,2);

cout << "Car1 is a " << car1.getBrand() << endl
<< "Its top speed is " << car1.getTopSpeed() << "km/h\n"
<< "And it has " << car1.getSeats() << " seats\n\n";

cout << "Car2 is a " << car2.getBrand() << endl
<< "Its top speed is " << car2.getTopSpeed() << "km/h\n"
<< "And it has " << car2.getSeats() << " seats\n\n";

car1.print();
car2.print();

return 0;
}


运行结果是:



从上面这个样例可以发现,即使派生类使用public方式来继承基类,也没有办法直接访问基类中的private成员,只能通过调用其基类的public成员函数(比如get与set函数)来间接访问private成员。这也从侧面反映C++ 中的private是一个很严格的属性。

那么有没有一种属性,它既不像public一样谁都可以碰,又没有private那样“小气”呢?

答案是肯定的,protected属性是介于public和private之间的一级保护。它可以在基类的定义及基类的友元中访问(这一点同private一样),但也能在基类的派生类中访问。

1.2其他要点

首先要说明的是,派生类是不会继承基类的构造函数的,但由于基类的构造函数必须声明为public,所以我们可以在派生类中随时访问。比如上面实例中的类Car构造函数:

//这里先直接调用基类的构造函数初始化基类的数据成员,再进行后续操作
Car::Car(string b,int ts,int s)
: Vehicle(b,ts)
{
setSeats(s);
}


在实例化派生类对象时,构造函数的调用顺序是先基类后派生类

在销毁派生类的对象时,析构函数的调用顺序是先派生类后基类

另外,当采用public、protected和private三种方式继承基类时,基类中的public、protected和private数据成员会有不用的变化,详情可以见书P383的表格。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: