C++面向对象程序设计的一些知识点(2)
1、C++中三种继承方式及派生类中访问控制规则
(1)、C++支持的三种继承方式是public、protected、private。C++允许一个类同时以不同的方式对不同的基类加以继承。
(2)、
继承方式 | 基类成员访问控制 | ||
public | protected | private | |
public | public | protected | no access |
protected | protected | protected | no access |
private | private | private |
no access |
注意:在派生类中,表中所述的访问控制“private”和“no access”存在很大的差别。对来自基类且在派生类中访问控制为“no access”的成员,
在派生类中是不可见的(自然,派生类的外部也不可见);对来自基类且在派生类中访问控制为“private”的子成员,在派生类内部可以访问它
们,但在派生类外部不可以访问它们。
2、派生类对象内存模型分析
(1)、程序运行时派生类对象或存在于函数栈中或存在于系统给程序分配的堆中,它是一段物理内存。
(2)、派生类与基类之间的关系是一种“is-a”的关系,否则在逻辑上必然造成混乱。
()
3、派生类对象的构造过程和析构过程
(1)、在继承方向上,先基类对象,后派生类子对象;在同一层次上,先包含类子对象,再本类子对象;如果在同一层次上存在多个包含类子
对象时,按照声明顺序来构造。
1 #include <iostream> 2 3 using namespace std; 4 5 class EmbededA_Root 6 { 7 public: 8 EmbededA_Root() 9 { 10 cout << "1_a:constructing embedded sub object A.\n"; 11 } 12 ~EmbededA_Root() 13 { 14 cout << "1_a:destructing embedded sub object A.\n"; 15 } 16 private: 17 }; 18 class EmbededB_Root 19 { 20 public: 21 EmbededB_Root() 22 { 23 cout << "1_b:constructing embedded sub object B.\n"; 24 } 25 ~EmbededB_Root() 26 { 27 cout << "1_b:destructing embedded sub object B.\n"; 28 } 29 private: 30 }; 31 class RootBase 32 { 33 public: 34 RootBase():embedA(), embedB() 35 { 36 cout << "1:constructing root base sub object.\n"; 37 } 38 ~RootBase() 39 { 40 cout << "1:destructing root base sub object.\n"; 41 } 42 private: 43 44 EmbededB_Root embedB; 45 EmbededA_Root embedA; 46 }; 47 class Base:RootBase 48 { 49 public: 50 Base() 51 { 52 cout << "2:constructing base sub object.\n"; 53 } 54 ~Base() 55 { 56 cout << "2:destructing base sub object.\n"; 57 } 58 private: 59 }; 60 class Derived:public Base 61 { 62 public: 63 Derived() 64 { 65 cout << "3:constructing derived sub object.\n"; 66 } 67 ~Derived() 68 { 69 cout << "3:destructing derived sub object.\n"; 70 } 71 private: 72 }; 73 74 int main() 75 { 76 { 77 Derived d; 78 } 79 int c; 80 cin >> c; 81 return 0; 82 }
运行结果是:
如果将类RootBase中的embedA和embedB声明顺序换一下的话,则结果是:
4、跨类的同名成员
(1)、派生类属性会隐藏其基类的同名属性,此时区分它们的方法是加上作用域限定符,即“积累名::属性名”。
(2)、在非多态的情况下,派生类同名函数永远使基类同名函数隐藏起来(即使成员函数的特征表不同)。
5、基类对象与派生类对象之间的转换
(1)、用派生类对象给基类对象赋值或者用派生类初始化基类引用;此时是安全的,通常我们也应该重新编写赋值运算符的重载。
(2)、用基类对象给派生类对象赋值;此时是危险的,不应该这么做。
(3)、基类指针指向派生类对象地址;基类指针至少包含指针值和允许访问范围这样两个属性,而且此时基类指针允许访问的范围仅限于派生类对象子对象。
(4)、派生类指针指向基类对象;此时是危险的,不应该这么做。
(5)、C++提供的类型转换运算符。
6、多继承
(1)、非虚拟基类多继承;
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 Base(int a) 9 { 10 this->a = a; 11 cout << "common base sub object being constructed.\n"; 12 } 13 void show() 14 { 15 cout << a << endl; 16 } 17 ~Base() 18 { 19 cout << "deleting common base sub object.\n"; 20 } 21 private: 22 int a; 23 }; 24 class B1:public Base 25 { 26 public: 27 B1(int a, int b1):Base(a) 28 { 29 this->b1 = b1; 30 cout << "base1 sub object being constructed.\n"; 31 } 32 void showBase() 33 { 34 show(); 35 } 36 ~B1() 37 { 38 cout << "deleting base1 sub object.\n"; 39 } 40 private: 41 int b1; 42 }; 43 class B2:public Base 44 { 45 public: 46 B2(int a, int b2):Base(a) 47 { 48 this->b2 = b2; 49 cout << "base2 sub object being constructed.\n"; 50 } 51 void showBase() 52 { 53 show(); 54 } 55 ~B2() 56 { 57 cout << "deleting base2 sub object.\n"; 58 } 59 private: 60 int b2; 61 }; 62 class D:public B2, public B1 63 { 64 public: 65 D(int a1, int b1, int a2, int b2, int d):B1(a1, b1), B2(a2, b2) 66 { 67 this->d = d; 68 cout << "derived sub object being constructed.\n"; 69 } 70 void showB1Base() 71 { 72 B1::showBase(); 73 } 74 void showB2Base() 75 { 76 B2::showBase(); 77 } 78 ~D() 79 { 80 cout << "deleting derived sub object.\n"; 81 } 82 private: 83 int d; 84 }; 85 86 int main() 87 { 88 { 89 D d(11, 2, 12, 3, 4); 90 d.B1::show(); 91 d.B2::show(); 92 d.B1::showBase(); 93 d.B2::showBase(); 94 d.showB1Base(); 95 d.showB2Base(); 96 } 97 int c; 98 cin >> c; 99 return 0; 100 }
此时基类对象在派生类对象中占有一个独立的内存空间。
(2)、虚拟基类多继承;
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 Base(int a) 9 { 10 this->a = a; 11 cout << "common base sub object being constructed.\n"; 12 } 13 void show() 14 { 15 cout << a << endl; 16 } 17 ~Base() 18 { 19 cout << "deleting common base sub object.\n"; 20 } 21 private: 22 int a; 23 }; 24 class B1:virtual public Base 25 { 26 public: 27 B1(int a, int b1):Base(a) 28 { 29 this->b1 = b1; 30 cout << "base1 sub object being constructed.\n"; 31 } 32 void showBase() 33 { 34 show(); 35 } 36 ~B1() 37 { 38 cout << "deleting base1 sub object.\n"; 39 } 40 private: 41 int b1; 42 }; 43 class B2:virtual public Base 44 { 45 public: 46 B2(int a, int b2):Base(a) 47 { 48 this->b2 = b2; 49 cout << "base2 sub object being constructed.\n"; 50 } 51 void showBase() 52 { 53 show(); 54 } 55 ~B2() 56 { 57 cout << "deleting base2 sub object.\n"; 58 } 59 private: 60 int b2; 61 }; 62 class D:public B1, public B2 63 { 64 public: 65 D(int a, int b1, int b2, int d):B1(a, b1), B2(a, b2), Base(a) 66 { 67 this->d = d; 68 cout << "derived sub object being cosntructed.\n"; 69 } 70 void showB1Base() 71 { 72 B1::showBase(); 73 } 74 void showB2Base() 75 { 76 B2::showBase(); 77 } 78 ~D() 79 { 80 cout << "deleting derived sub object.\n"; 81 } 82 83 private: 84 int d; 85 }; 86 87 int main() 88 { 89 { 90 D d(11, 2, 3, 4); 91 92 d.showB1Base(); 93 d.showB2Base(); 94 } 95 int c; 96 cin >> c; 97 return 0; 98 }
此时基类子对象只包含一个。
7、继承综合应用实例
类关系UML图如图:
代码:
1 #include <iostream> 2 3 using namespace std; 4 5 class Employee 6 { 7 public: 8 Employee(char *name) 9 { 10 no = companyEmployee++; 11 grade = 1; 12 pName = new char[strlen(name) + 1]; 13 strcpy(pName, name); 14 totalPay = 0.0; 15 } 16 ~Employee() 17 { 18 delete [] pName; 19 } 20 public: 21 void pay(){} 22 void promote(int increment) 23 { 24 grade += increment; 25 } 26 void displayInfo(){} 27 protected: 28 char *pName; 29 int no; 30 int grade; 31 double totalPay; 32 static int companyEmployee; 33 private: 34 }; 35 int Employee::companyEmployee = 100; // 静态变量初始化 36 37 class Technician:public Employee 38 { 39 public: 40 Technician(char *name, int workHours = 0):Employee(name) 41 { 42 rate = 100; // 100元/小时 43 this->workHours = workHours; 44 } 45 void setWorkhours(int workHours) 46 { 47 this->workHours = workHours; 48 } 49 void pay() 50 { 51 totalPay = workHours*rate; 52 } 53 void displayInfo() 54 { 55 promote(2); 56 cout << "兼职技术人员:" << pName << ",编号:" << no 57 << ",级别:" << grade << ",已付本月工资:" 58 << totalPay << endl; 59 } 60 private: 61 double rate; 62 int workHours; 63 }; 64 class SaleMan:virtual public Employee 65 { 66 public: 67 SaleMan(char *name, int sales = 0):Employee(name) 68 { 69 ratio = 0.004; 70 this->sales = sales; 71 } 72 void setSales(double sales) 73 { 74 this->sales = sales; 75 } 76 void pay() 77 { 78 totalPay = sales*ratio; 79 } 80 void displayInfo() 81 { 82 promote(2); 83 cout << "推销员:" << pName << ",编号:" << no 84 << ",级别:" << grade << ",已付本月工资:" 85 << totalPay << endl; 86 } 87 protected: 88 double sales; 89 double ratio; 90 }; 91 class Manager:virtual public Employee 92 { 93 public: 94 Manager(char *name, int monthlyPay = 6000):Employee(name) 95 { 96 this->monthlyPay = monthlyPay; 97 } 98 void setMonthlyPay(double monthlyPay) 99 { 100 this->monthlyPay = monthlyPay; 101 } 102 void pay() 103 { 104 totalPay = monthlyPay; 105 } 106 void displayInfo() 107 { 108 promote(3); 109 cout << "经理:" << pName << ",编号:" << no 110 << ",级别:" << grade << ",已付本月工资:" 111 << totalPay << endl; 112 } 113 protected: 114 double monthlyPay; 115 }; 116 class SaleManager:public SaleMan, public Manager 117 { 118 public: 119 SaleManager(char *name):SaleMan(name), Manager(name), Employee(name) 120 { 121 monthlyPay = 4000; 122 ratio = 0.002; 123 } 124 void pay() 125 { 126 totalPay = monthlyPay + sales*ratio; 127 } 128 void displayInfo() 129 { 130 promote(2); 131 cout << "销售经理:" << pName << ",编号:" << no 132 << ",级别:" << grade << ",已付本月工资:" 133 << totalPay << endl; 134 } 135 private: 136 }; 137 138 int main() 139 { 140 Technician t("zhang san"); 141 t.setWorkhours(100); 142 t.pay(); 143 t.displayInfo(); 144 145 SaleManager sm("li si"); 146 sm.setMonthlyPay(7000); 147 sm.setSales(1000); 148 sm.pay(); 149 sm.displayInfo(); 150 int c; 151 cin >> c; 152 return 0; 153 }