當前位置:
首頁 > 知識 > C++繼承:繼承與構造函數、派生類到基類的轉換

C++繼承:繼承與構造函數、派生類到基類的轉換

一、不能自動繼承的成員函數

構造函數(包括拷貝構造函數)

析構函數

=運算符

二、繼承與構造函數

基類的構造函數不被繼承,派生類中需要聲明自己的構造函數。

聲明構造函數時,只需要對本類中新增成員進行初始化,對繼承來的基類成員的初始化調用基類構造函數完成(如果沒有給出則默認調用默認構造函數)。

派生類的構造函數需要給基類的構造函數傳遞參數

C++ Code

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

#include <iostream>

using namespace std;

class ObjectB

{

public:

ObjectB(int objb) : objb_(objb)

{

cout << "ObjectB ..." << endl;

}

~ObjectB()

{

cout << "~ObjectB ..." << endl;

}

int objb_;

};

class ObjectD

{

public:

ObjectD(int objd) : objd_(objd)

{

cout << "ObjectD ..." << endl;

}

~ObjectD()

{

cout << "~ObjectD ..." << endl;

}

int objd_;

};

class Base

{

public:

Base(int b) : b_(b), objb_(111)

{

cout << "Base ..." << endl;

}

Base(const Base &other) : objb_(other.objb_), b_(other.b_)

{

}

~Base()

{

cout << "~Base ..." << endl;

}

int b_;

ObjectB objb_;

};

class Derived : public Base

{

public:

Derived(int b, int d) : d_(d), Base(b), objd_(222)

{

cout << "Derived ..." << endl;

}

Derived(const Derived &other) : d_(other.d_), objd_(other.objd_), Base(other)

{

}

~Derived()

{

cout << "~Derived ..." << endl;

}

int d_;

ObjectD objd_;

};

int main(void)

{

Derived d(100, 200);

cout << d.b_ << " " << d.d_ << endl;

Base b1(100);

Base b2(b1);

cout << b2.b_ << endl;

Derived d2(d);

return 0;

}

C++繼承:繼承與構造函數、派生類到基類的轉換

從輸出可以看出:

派生類對象的構造次序:

先調用基類對象成員的構造函數,接著是基類的構造函數,然後是派生類的對象成員的構造函數,最後是派生類自身的構造函數。

也可以這樣來看:構造函數執行的順序是先執行初始化列表,然後是函數體。初始化列表參數多個且其中有調用基類構造函數時,先執行基類構造函數(從最遠的開始,如果多重繼承則按繼承的順序);其他對象成員若不止一個,則按定義的順序構造,與初始化列表順序無關。關於初始化列表可以參考這裡

析構的順序與構造的順序相反。

三、友元關係、靜態成員與繼承

友元關係不能被繼承

靜態成員無所謂繼承

C++ Code

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

#include <iostream>

using namespace std;

class Base

{

public:

static int b_;

};

int Base::b_ = 100;

class Derived : public Base

{

};

int main(void)

{

Base b;

Derived d;

cout << Base::b_ << endl;

cout << b.b_ << endl;

cout << Derived::b_ << endl;

cout << d.b_ << endl;

return 0;

}

都能訪問,輸出100,但推薦使用類::xx 訪問,如b.b_ 訪問存在歧義,實際上static成員不屬於任一對象。

四、派生類到基類的轉換

當派生類以public方式繼承基類時,編譯器可自動執行的轉換(向上轉型 upcasting 安全轉換)


派生類對象指針自動轉化為基類對象指針

派生類對象引用自動轉化為基類對象引用

派生類對象自動轉換為基類對象(特有的成員消失)

當派生類以private/protected方式繼承基類時


派生類對象指針(引用)轉化為基類對象指針(引用)需用強制類型轉化。但不能用static_cast,要用reinterpret_cast

不能把派生類對象強制轉換為基類對象

C++ Code

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

#include <iostream>

#include <string>

using namespace std;

class Employee

{

public:

Employee(const string &name, const int age, const int deptno) : name_(name),

age_(age), deptno_(deptno)

{

}

private:

string name_;

int age_;

int deptno_;

};

class Manager : public Employee

{

public:

Manager(const string &name, const int age, const int deptno, int level)

: Employee(name, age, deptno), level_(level)

{

}

private:

int level_;

};

class Manager2 : private Employee

{

public:

Manager2(const string &name, const int age, const int deptno, int level)

: Employee(name, age, deptno), level_(level)

{

}

private:

int level_;

};

int main(void)

{

Employee e1("zhangsan", 25, 20);

Manager m1("lisi", 38, 20, 10);

Manager2 m2("wangwu", 40, 15, 8);

Employee *pe;

Manager *pm;

Manager2 *pm2;

pe = &e1;

pm = &m1;

pm2 = &m2;

pe = &m1; // 派生類對象指針可以轉化為基類對象指針。將派生類對象看成基類對象

//pm = &e1; // 基類對象指針無法轉化為派生類對象指針。無法將基類對象看成是派生類對象

e1 = m1; // 派生類對象可以轉化為基類對象。將派生類對象看成基類對象

// 會產生對象切割(派生類特有成員消失)。object slicing

//pe = pm2; //私有或保護繼承的時候,派生類對象指針不可以自動轉化為基類對象指針

pe = reinterpret_cast<Employee *>(pm2);

//e1 = m2; // 私有或保護繼承的時候,派生類對象無法轉化為基類對象。

//e1 = reinterpret_cast<Employee>(m2); // 私有或保護繼承的時候,派生類對象無法強制轉化為基類對象。

pm = static_cast<Manager *>(pe); // 基類指針可以強制轉化為派生類指針,但是不安全

//m1 = reinterpret_cast<Manager>e1; // 基類對象無法強制轉化為派生類對象

return 0;

}

五、基類到派生類的轉換

基類對象指針(引用)可用強制類型轉換為派生類對象指針(引用), 而基類對象無法執行這類轉換.

向下轉型不安全,沒有自動轉換的機制

// 從語法上來演示基類對象可以轉化為派生類對象,但是沒有意義

1、轉換構造函數:

Manager(const Employee& other) : Employee(other), level_(-1)

{

}

2、類型轉換運算符:

Employee::operator Manager()

{


return Manager(name_, age_, deptno_, -1);

}

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

Kubernetes 最佳實踐:正常終止
Idea 阿里代碼規約插件安裝

TAG:程序員小新人學習 |