- Expert C++
- Vardan Grigoryan Shunguang Wu
- 458字
- 2021-06-24 16:34:03
Inheritance
Inheritance is a programming concept that allows us to reuse classes. Programming languages provide different implementations of inheritance, but the general rule always stands: the class relationship should answer the is-a question. For example, a Car is-a Vehicle, which allows us to inherit the Car from the Vehicle:
class Vehicle {
public:
void move();
};
class Car : public Vehicle {
public:
Car();
// ...
};
The Car now has the move() member function derived from the Vehicle. Inheritance itself represents a generalization/specialization relationship, where the parent class (Vehicle) is the generalization and the child class (Car) is the specialization.
You should only consider using inheritance if it is absolutely necessary. As we mentioned earlier, classes should satisfy the is-a relationship, and sometimes, this is a bit tricky. Consider the Square and Rectangle classes. The following code declares the Rectangle class in its simplest possible form:
class Rectangle {
public:
// argument checks omitted for brevity
void set_width(int w) { width_ = w; }
void set_height(int h) { height_ = h; }
int area() const { return width_ * height_; }
private:
int width_;
int height_;
};
The Square is-a Rectangle, so we could easily inherit it from the Rectangle:
class Square : public Rectangle {
public:
void set_side(int side) {
set_width(side);
set_height(side);
}
int area() {
area_ = Rectangle::area();
return area_;
}
private:
int area_;
};
The Square extends the Rectangle by adding a new data member, area_, and overwriting the area() member function with its own implementation. In practice, the area_ and the way we calculate its value are redundant; we did this to demonstrate a bad class design and to make the Square extend its parent to some extent. Soon, we will conclude that the inheritance, in this case, is a bad design choice. Square is a Rectangle, so it should be used as a Rectangle wherever the Rectangle is used, as shown here:
void make_big_rectangle(Rectangle& ref) {
ref->set_width(870);
ref->set_height(940);
}
int main() {
Rectangle rect;
make_big_rectangle(rect);
Square sq;
// Square is a Rectangle
make_big_rectangle(sq);
}
The make_big_rectangle() function takes a reference to the Rectangle and the Square inherits it, so it's totally fine to send a Square object to the make_big_rectangle() function; the Square is-a a Rectangle. This example of the successful substitution of a type with its subtype is known as the Liskov Substitution Principle. Let's find out why this substitution works in practice and then decide if we made a design mistake by inheriting the Square from the Rectangle (yes, we did).
- AngularJS入門與進階
- The Supervised Learning Workshop
- 用Python實現深度學習框架
- Java:High-Performance Apps with Java 9
- Learning OpenStack Networking(Neutron)(Second Edition)
- 大數據分析與應用實戰:統計機器學習之數據導向編程
- 51單片機C語言開發教程
- Fast Data Processing with Spark(Second Edition)
- RubyMotion iOS Develoment Essentials
- HTML5+CSS3+JavaScript 從入門到項目實踐(超值版)
- 零基礎看圖學ScratchJr:少兒趣味編程(全彩大字版)
- Hacking Android
- Mastering OpenStack
- 基于MATLAB的控制系統仿真及應用
- 一覽眾山小:ASP.NET Web開發修行實錄