C++advanced面向objectprogrammingtutorial

LearningC++in advanced面向objectprogrammingfeatures, includinginheritance, polymorphism, 虚functionetc.

返回tutoriallist

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() and calculateArea().
  • creation具体 graph形class, such asCircle, 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 容.