类和对象 3

继承

面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。

当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类

子类的访问权限

public protected private
public yes yes yes
protected yes yes no
private no no no

对外的访问权限

public protected private
public public protected private
protected protected protected private
private no no no

菱形继承(A->D, B->D, C->(A,B))

class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};

这个继承会使 D 创建两个对象,要解决上面问题就要用虚拟继承格式

格式:class 类名: virtual 继承方式 父类名

class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};

虚继承–(在创建对象的时候会创建一个虚表)在创建父类对象的时候

A:virtual public D
B:virtual public D

访问控制和继承

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。 我们可以根据访问权限总结出不同的访问类型,如下所示:

访问 public protected private
同一个类 yes yes yes
派生类 yes yes no
外部的类 yes no no

一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数
  • 基类的重载运算符
  • 基类的友元函数

当使用不同类型的继承时,遵循以下几个规则:

  • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
  • 保护继承(protected): 当一个类派生自保护基类时,基类的公有保护成员将成为派生类的保护成员。
  • 私有继承(private):当一个类派生自私有基类时,基类的公有保护成员将成为派生类的私有成员。

运算符重载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<iostream>
using namespace std;

class Point {
public:
    Point() {}
    Point(int x, int y) : x(x), y(y) {}
    Point(const Point &obj) : x(obj.x), y(obj.y) {
        cout << "copy constructor" << endl;
    }
    int operator()(int num) {
        return this->x + this->y + num;
    }
    int operator[](string str) {
        if (str == "x") return this->x;
        if (str == "y") return this->y;
        return 0;
    }
    Point operator-(const Point &a) {
        Point ret;
        ret.x = this->x - a.x;
        ret.y = this->y - a.y;
        return ret;
    }
    friend ostream &operator<<(ostream &, const Point &);
    friend Point operator+(const Point &, const Point &);
private:
    int x, y;
};

Point operator+(const Point &a, const Point &b) {
    Point ret;
    ret.x = a.x + b.x;
    ret.y = a.y + b.y;
    return ret;
}

ostream &operator<<(ostream &output, const Point &a) {
    output << "<class Point>(" << a.x << ", " << a.y << ")";
    return output;
}

int main() {
    Point a(2, 4), b(5, 3);
    Point c = a + b;
    Point d = a + b + c;
    Point e = d - b;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    cout << d << endl;
    cout << e << endl;
    return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <iostream>
#include <algorithm>
using namespace std;

class intArray {
private:
    int n;
    int *p;
public:
    intArray(int n) : n(n) {
        this->p = new int[n];
    }
    intArray(const intArray &obj) : n(obj.n) {
        this->p = new int[n];
        for (int i = 0; i < n; i++) {
            this->p[i] = obj.p[i];
        }
    }
    int size() {
        return n;
    }
    int find(int num) {
        for (int i = 0; i < n; i++) {
            if (p[i] == num) return i;
        }
        return -1;
    }
    void sort(int op) {
        if (op) std::sort(p, p + n);
        else std::sort(p, p + n, [](int a, int b) {return a > b;});
        return ;
    }
    void reverse() {
        std::reverse(p, p + n);
        return ;
    }
    int &operator[](int ind) {
        if (ind < 0) return this->p[n + ind];
        return this->p[ind];
    }
    void operator+=(int num) {
        for (int i = 0; i < n; i++) {
            this->p[i] += num;
        }
        return ;
    }
    intArray &operator++() {
        for (int i = 0; i < n; i++) {
            this->p[i]++;
        }
        return *this;
    }
    intArray operator++(int x) {
        intArray ret = *this;
        for (int i = 0; i < n; i++) {
            this->p[i]++;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &, const intArray &);
    ~intArray() {
        delete[] this->p;
    }
};

ostream &operator<<(ostream &output, const intArray &a) {
    output << "<class intArray>:";
    for (int i = 0; i < a.n; i++) {
        output << " " << a.p[i];
    }
    return output;
}

int main() {
    intArray a(10);
    for (int i = 0; i < 10; i++) {
        a[i] = i;
    }
    cout << a.size() << endl;
    cout << a.find(3) << endl;
    cout << a[4] << endl;
    cout << a[-2] << endl;
    a += 5;
    cout << a << endl;
    a.sort(1);
    cout << a << endl;
    a.sort(0);
    cout << a << endl;
    a.reverse();
    cout << a << endl;
    cout << (a++) << endl;
    cout << (++a) << endl;
    return 0;
}