1. inheritance advanced features
1.1 inheritance concepts复习
inheritance is 面向objectprogramming 三 big features之一, 它允许creation一个 new class (forkclass) 来inheritance另一个class (基class) property and method.
1.2 访问控制
C++in has 三种访问控制修饰符:
- public: 公共成员, in 任何地方都可以访问.
- protected: 保护成员, 只能 in class in 部 and forkclassin访问.
- private: 私 has 成员, 只能 in class in 部访问.
1.2.1 不同inheritance方式 for 访问permission 影响
| 基class成员访问permission | publicinheritance | protectedinheritance | privateinheritance |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | 不可访问 | 不可访问 | 不可访问 |
1.3 constructfunction and 析构function inheritance
constructfunction and 析构function不能被inheritance, 但forkclass constructfunction会自动调用基class constructfunction, forkclass 析构function会自动调用基class 析构function.
1.3.1 constructfunction 调用顺序
#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "Base constructfunction" << endl;
}
~Base() {
cout << "Base 析构function" << endl;
}
};
class Derived : public Base {
public:
Derived() {
cout << "Derived constructfunction" << endl;
}
~Derived() {
cout << "Derived 析构function" << endl;
}
};
int main() {
Derived d;
// 输出顺序: Baseconstructfunction → Derivedconstructfunction → Derived析构function → Base析构function
return 0;
}
1.3.2 带parameter constructfunction
#include <iostream>
#include <string>
using namespace std;
class Person {
protected:
string name;
int age;
public:
Person(const string& n, int a) : name(n), age(a) {
cout << "Person constructfunction" << endl;
}
};
class Student : public Person {
private:
string studentID;
public:
// forkclassconstructfunction必须显式调用基classconstructfunction
Student(const string& n, int a, const string& id) :
Person(n, a), studentID(id) {
cout << "Student constructfunction" << endl;
}
void display() {
cout << "姓名: " << name << ", 年龄: " << age << ", 学号: " << studentID << endl;
}
};
int main() {
Student s("张三", 18, "2023001");
s.display();
return 0;
}
2. polymorphism性
2.1 polymorphism concepts
polymorphism is 面向objectprogramming 三 big features之一, 它允许不同class object for 同一message做出不同 response.
C++in polymorphism主要through虚functionimplementation.
2.2 虚function
虚function is in 基classin声明 带 has virtual关键字 成员function, 它允许forkclass重写 (override) 该function.
2.2.1 虚function basic用法
#include <iostream>
using namespace std;
class Animal {
public:
// 虚function
virtual void makeSound() {
cout << "动物发出声音" << endl;
}
};
class Dog : public Animal {
public:
// 重写虚function
void makeSound() override {
cout << "汪汪汪" << endl;
}
};
class Cat : public Animal {
public:
// 重写虚function
void makeSound() override {
cout << "喵喵喵" << endl;
}
};
int main() {
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
// polymorphism: through基class指针调用forkclass method
animal1->makeSound(); // 输出: 汪汪汪
animal2->makeSound(); // 输出: 喵喵喵
delete animal1;
delete animal2;
return 0;
}
2.3 纯虚function and abstractionclass
纯虚function is in 基classin声明 没 has implementation 虚function, 它要求所 has forkclass必须implementation该function. package含纯虚function class称 for abstractionclass.
2.3.1 纯虚function 声明
class Shape {
public:
// 纯虚function
virtual double calculateArea() const = 0;
// 普通虚function
virtual void display() const {
cout << "这 is a 形状" << endl;
}
// 析构function应该声明 for 虚function
virtual ~Shape() {}
};
2.3.2 abstractionclass using
#include <iostream>
#include <cmath>
using namespace std;
class Shape {
public:
virtual double calculateArea() const = 0;
virtual void display() const {
cout << "面积: " << calculateArea() << endl;
}
virtual ~Shape() {}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double calculateArea() const override {
return M_PI * radius * radius;
}
void display() const override {
cout << "圆形, ";
Shape::display();
}
};
class Rectangle : public Shape {
private:
double width;
double height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double calculateArea() const override {
return width * height;
}
void display() const override {
cout << "矩形, ";
Shape::display();
}
};
int main() {
// Shape s; // error: abstractionclass不能instance化
Shape* shapes[2];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
for (int i = 0; i < 2; i++) {
shapes[i]->display();
delete shapes[i];
}
return 0;
}
3. 虚function表 and 动态绑定
3.1 虚function表 concepts
虚function表 (vtable) is C++implementationpolymorphism coremechanism. 每个package含虚function class都 has 一个虚function表, 表instore了该class所 has 虚function 地址.
当creation一个package含虚function class object时, object会package含一个指向虚function表 指针 (vptr) .
3.2 动态绑定vs静态绑定
- 静态绑定 (早绑定) : in 编译时确定调用哪个function, 适用于普通function and 非虚function.
- 动态绑定 (晚绑定) : in run时确定调用哪个function, 适用于虚function.
4. how heavyinheritance
4.1 how heavyinheritance concepts
how heavyinheritance is 指一个forkclass同时inheritance自 many 个基class.
4.1.1 how heavyinheritance basic语法
#include <iostream>
#include <string>
using namespace std;
class Person {
protected:
string name;
public:
Person(const string& n) : name(n) {}
void eat() {
cout << name << " in 吃饭" << endl;
}
};
class Employee {
protected:
string company;
public:
Employee(const string& c) : company(c) {}
void work() {
cout << " in " << company << " 工作" << endl;
}
};
// how heavyinheritance
class managementr : public Person, public Employee {
public:
managementr(const string& n, const string& c) :
Person(n), Employee(c) {}
void manage() {
cout << name << " in " << company << " management员工" << endl;
}
};
int main() {
managementr m("张三", "ABC公司");
m.eat(); // inheritance自Person
m.work(); // inheritance自Employee
m.manage(); // 自己 method
return 0;
}
4.2 菱形inheritanceissues
菱形inheritance is 指一个forkclassinheritance自两个基class, 而这两个基class又inheritance自同一个基class circumstances.
4.2.1 菱形inheritance issues
#include <iostream>
using namespace std;
class Animal {
protected:
int age;
public:
Animal(int a) : age(a) {}
};
class Mammal : public Animal {
public:
Mammal(int a) : Animal(a) {}
};
class Bird : public Animal {
public:
Bird(int a) : Animal(a) {}
};
// 菱形inheritance: 同时inheritanceMammal and Bird
class Bat : public Mammal, public Bird {
public:
// issues: 需要初始化两个Animal基class
Bat(int a) : Mammal(a), Bird(a) {}
void display() {
// issues: ambiguous (歧义) , 不知道访问哪个age
// cout << "年龄: " << age << endl; // error
cout << "Mammal年龄: " << Mammal::age << endl;
cout << "Bird年龄: " << Bird::age << endl;
}
};
int main() {
Bat b(5);
b.display();
return 0;
}
4.2.2 虚拟inheritance解决菱形inheritanceissues
#include <iostream>
using namespace std;
class Animal {
protected:
int age;
public:
Animal(int a) : age(a) {
cout << "Animal constructfunction" << endl;
}
};
// using虚拟inheritance
class Mammal : virtual public Animal {
public:
Mammal(int a) : Animal(a) {
cout << "Mammal constructfunction" << endl;
}
};
// using虚拟inheritance
class Bird : virtual public Animal {
public:
Bird(int a) : Animal(a) {
cout << "Bird constructfunction" << endl;
}
};
class Bat : public Mammal, public Bird {
public:
// 虚拟inheritance after , 只需要初始化一次Animal基class
Bat(int a) : Animal(a), Mammal(a), Bird(a) {
cout << "Bat constructfunction" << endl;
}
void display() {
// 现 in 可以直接访问age
cout << "年龄: " << age << endl;
}
};
int main() {
Bat b(5);
b.display();
return 0;
}
5. run时class型识别 (RTTI)
5.1 RTTI concepts
run时class型识别 (RTTI) is C++providing 一种mechanism, 允许 in run时获取object class型information.
5.2 typeid运算符
typeid运算符用于获取表达式 class型information, 返回一个type_infoobject.
5.2.1 typeid using
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
};
int main() {
Base* b1 = new Base();
Base* b2 = new Derived();
// 获取class型information
cout << "b1 class型: " << typeid(*b1).name() << endl;
cout << "b2 class型: " << typeid(*b2).name() << endl;
// 比较class型
if (typeid(*b1) == typeid(Base)) {
cout << "b1 is Baseclass型" << endl;
}
if (typeid(*b2) == typeid(Derived)) {
cout << "b2 is Derivedclass型" << endl;
}
delete b1;
delete b2;
return 0;
}
5.3 dynamic_cast运算符
dynamic_cast运算符用于 in inheritance层次structureinforclass型转换, 它会 in run时check转换 is 否security.
5.3.1 dynamic_cast using
#include <iostream>
using namespace std;
class Shape {
public:
virtual double calculateArea() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double calculateArea() const override {
return 3.14159 * radius * radius;
}
double getRadius() const {
return radius;
}
};
class Rectangle : public Shape {
private:
double width;
double height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double calculateArea() const override {
return width * height;
}
double getWidth() const {
return width;
}
double getHeight() const {
return height;
}
};
void processShape(Shape* shape) {
cout << "面积: " << shape->calculateArea() << endl;
// 尝试转换 for Circle
Circle* circle = dynamic_cast(shape);
if (circle) {
cout << "这 is a 圆形, 半径: " << circle->getRadius() << endl;
}
// 尝试转换 for Rectangle
Rectangle* rectangle = dynamic_cast(shape);
if (rectangle) {
cout << "这 is a 矩形, 宽: " << rectangle->getWidth()
<< ", high : " << rectangle->getHeight() << endl;
}
}
int main() {
Shape* shapes[2];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
for (int i = 0; i < 2; i++) {
processShape(shapes[i]);
delete shapes[i];
}
return 0;
}
6. 面向objectdesignprinciples
6.1 单一职责principles (SRP)
一个class应该只 has 一个引起它变化 原因, 即一个class只负责一项职责.
6.2 开放-封闭principles (OCP)
Software entities (classes, modules, functions, etc.) should be open for extension, closed for modification.
6.3 里氏replaceprinciples (LSP)
子class应该able toreplace其父class, 并且不影响程序 正确性.
6.4 依赖倒置principles (DIP)
high 层module不应该依赖 low 层module, 两者都应该依赖于abstraction. abstraction不应该依赖于细节, 细节应该依赖于abstraction.
6.5 interface隔离principles (ISP)
客户端不应该依赖于它不using interface.
实践case: graph形绘制system
writing一个C++程序, implementation一个 simple graph形绘制system, using面向object design思想, includingabstractionclass, polymorphismetc.features.
requirementsanalysis
- creation一个abstraction
Shapeclass, package含纯虚functiondraw()andcalculateArea(). - creation具体 graph形class, such as
Circle,Rectangle,Triangle, inheritance自Shapeclass并implementation相应 method. - creation一个
Shapemanagementrclass, 用于management and 绘制所 has graph形. - in 主functionintestsystem, creation不同 graph形object并绘制它们.
referencecode
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// abstraction基class
class Shape {
public:
virtual void draw() const = 0;
virtual double calculateArea() const = 0;
virtual ~Shape() {}
};
// 圆形class
class Circle : public Shape {
private:
double x, y; // 圆心坐标
double radius;
public:
Circle(double x_, double y_, double r) : x(x_), y(y_), radius(r) {}
void draw() const override {
cout << "绘制圆形: 圆心(" << x << ", " << y << "), 半径" << radius << endl;
}
double calculateArea() const override {
return M_PI * radius * radius;
}
};
// 矩形class
class Rectangle : public Shape {
private:
double x1, y1; // left on 角坐标
double x2, y2; // right under 角坐标
public:
Rectangle(double x1_, double y1_, double x2_, double y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
void draw() const override {
cout << "绘制矩形: left on 角(" << x1 << ", " << y1
<< "), right under 角(" << x2 << ", " << y2 << ")" << endl;
}
double calculateArea() const override {
double width = abs(x2 - x1);
double height = abs(y2 - y1);
return width * height;
}
};
// 三角形class
class Triangle : public Shape {
private:
double x1, y1;
double x2, y2;
double x3, y3;
public:
Triangle(double x1_, double y1_, double x2_, double y2_, double x3_, double y3_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_), x3(x3_), y3(y3_) {}
void draw() const override {
cout << "绘制三角形: 点1(" << x1 << ", " << y1
<< "), 点2(" << x2 << ", " << y2
<< "), 点3(" << x3 << ", " << y3 << ")" << endl;
}
double calculateArea() const override {
// using海伦公式计算三角形面积
double a = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
double b = sqrt(pow(x3 - x2, 2) + pow(y3 - y2, 2));
double c = sqrt(pow(x1 - x3, 2) + pow(y1 - y3, 2));
double s = (a + b + c) / 2;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
};
// graph形management器class
class Shapemanagementr {
private:
vector shapes;
public:
~Shapemanagementr() {
// 释放所 has graph形object
for (Shape* shape : shapes) {
delete shape;
}
}
void addShape(Shape* shape) {
shapes.push_back(shape);
}
void drawAll() const {
cout << "绘制所 has graph形: " << endl;
for (const Shape* shape : shapes) {
shape->draw();
cout << "面积: " << shape->calculateArea() << endl;
cout << "------------------------" << endl;
}
}
double calculateTotalArea() const {
double totalArea = 0;
for (const Shape* shape : shapes) {
totalArea += shape->calculateArea();
}
return totalArea;
}
};
int main() {
Shapemanagementr manager;
// 添加不同 graph形
manager.addShape(new Circle(0, 0, 5));
manager.addShape(new Rectangle(0, 0, 4, 6));
manager.addShape(new Triangle(0, 0, 0, 4, 3, 0));
// 绘制所 has graph形
manager.drawAll();
// 计算总面积
cout << "所 has graph形 总面积: " << manager.calculateTotalArea() << endl;
return 0;
}
run结果
绘制所 has graph形: 绘制圆形: 圆心(0, 0), 半径5 面积: 78.5398 ------------------------ 绘制矩形: left on 角(0, 0), right under 角(4, 6) 面积: 24 ------------------------ 绘制三角形: 点1(0, 0), 点2(0, 4), 点3(3, 0) 面积: 6 ------------------------ 所 has graph形 总面积: 108.5398
互动练习
练习1: creation一个abstraction Vehicleclass, package含纯虚functionstart() and stop(). 然 after creation具体 车辆class, such asCar, Bike, Truck, inheritance自Vehicleclass并implementation相应 method.
练习2: modify实践casein graph形绘制system, 添加一个Squareclass (正方形) , 并 in Shapemanagementrclassin添加deletegraph形 functions.
练习3: creation一个Employeeclass层次structure, package含基classEmployee and forkclassmanagementr, Developer, Designer. 每个class都 has 自己 property and method, usingpolymorphism来展示不同员工 工作 in 容.