1 publicpublic public protected protected privateinaccessible publicprivate X
1单一继承 public-->public 访问控制 public protected -->protected # # private-->inaccessible 用于规定从基类 继承的成员在派 生类中的访问限制。 public-->private + + - X + - protected -->private # - private-->inaccessible - X
1 单一继承 class Pen{ class Cpen: pulic Pen{ public: enum ink{off, on}; void set_status(ink); void set_location(int, int); private: int x; int y; ink status; }; void set_color(int); private: int color; };
1 单一继承 Pen - x, y, status CPen p; +void set_status(ink); p. x=5; +void set_location(int, int) //x是不可访问成员 CPen 继 承 的 X x, y, status p. set_status(Pen: : on); √ p. color=1; +void set_status(ink); //color是私有成员 +void set_location(int, int) p. set_color(1); -color +void set_color(int) × 例 4. 1_133 × √
2 保护成员:在类外不可见(同私有成员),在派生类中 可见(同公有成员) class Pen{ class Cpen: pulic Pen{ public: enum ink{off, on}; void set_status(ink); void set_location(int, int); private: void set_color(int); private: int color; void display(){cout<<status × <<color<<endl; } int x; int y; ink status; };
方案1 class Pen{ class Cpen: pulic Pen{ public: enum ink{off, on}; void set_status(ink); void set_color(int); private: ink get_status(){return status; } int color; void set_location(int, int); void display(){cout<<get_status( ) private: int x; int y; ink status; }; <<color<<endl; } }; 例 4. 2_142_1
方案2 class Pen{ class Cpen: pulic Pen{ public: enum ink{off, on}; void set_color(int); void set_status(ink); private: void set_location(int, int); int color; private: void display(){cout<<status int x; int y; protected: ink status; }; <<color<<endl; } }; 例 4. 2_142_2
class BC 1{ class DC: public BC 1, public BC 2 private: {private: int x; public: void set_x(int a){x=a; } }; class BC 2{ int main() private: {DC d 1; int x; d 1. set_x(999); public: d 1. BC 1: : set_x(111); void set_x(int a){x=a; } d 1. BC 2: : set_x(222); } 例4. 4_163
3 多继承 d 1 BC 1 - int x + set_x +set_x DC X int x + set_x 111 BC 2: : x 222 DC: : x 999 BC 2 - int x + BC 1: : x + X int x - int x + set_x BC 2
class BC{ public: private: int y; BC(){cout<<"BC: : () executes. . . n"; } ~BC(){cout<<"~BC: : () executes. . . n"; } private: int x; }; class DC: public BC{ public: DC() : BC() {cout<<"DC: : () executes. . . n"; } ~DC(){cout<<"~DC: : () executes. . . n"; } 例 4. 3_147 }; int main() { DC d; } BC: : () executes DC: : () executes ~BC: : () executes
class BC{ public: private: int y; BC(int a){cout<<"BC: : (int) executes. . . n"; x=a; } ~BC(){cout<<"~BC: : () executes. . . n"; } private: }; int main() { int x; DC d; } class DC: public BC{ public: DC()× {cout<<"DC: : () executes. . . n"; } ~DC(){cout<<"~DC: : () executes. . . n"; } 例 4. 3_148
class BC{ 方案1 public: private: int y; BC(){cout<<"BC: : ( ) executes. . . n"; } BC(int a){cout<<"BC: : (int) executes. . . n"; x=a; } ~BC(){cout<<"~BC: : () executes. . . n"; } private: int x; }; int main() { DC d; } }; class DC: public BC{ public: DC() {cout<<"DC: : () executes. . . n"; } ~DC(){cout<<"~DC: : () executes. . . n"; } BC: : () executes DC: : () executes ~BC: : () executes 例 4. 3_148_1
class BC{ private: 方案2 public: int y; BC(int a){cout<<"BC: : (int) executes. . . n"; x=a; } }; int main() ~BC(){cout<<"~BC: : () executes. . . n"; } { private: int x; DC d; } class DC: public BC{ public: DC(): BC(5) {cout<<"DC: : () executes. . . n"; } ~DC(){cout<<"~DC: : () executes. . . n"; } BC: : (int) executes DC: : () executes ~BC: : () executes 例 4. 3_148_2
派生类对象内存映像 例11. 4 class CBase{ public: int b 0; CBase() { b 0=0 x 01; } }; class CDerived : public CBase 1, public CBase 2 { public: int b; CDerived() { b=0 x 21; } }; class CBase 1 : public CBase{ public: int b 1; CBase 1() { b 1=0 x 11; } }; void main() { CDerived obj; } 起始地址→ b 00 00 00 12 b 2 00 00 00 01 b 0 00 00 00 11 b 1 00 00 00 01 b 0 …… CDerived 对象 00 00 00 21 CBase 2 对象 地 址 增 加 方 向 CBase 1 对象 class CBase 2 : public CBase{ public: int b 2; CBase 2() { b 2=0 x 12; } }; 存储内容 变量 ……
class BC 1{ class DC: public BC 1, public BC 2 private: { int x; }; public: int main() void set_x(int a){x=a; } {DC d 1; }; d 1. set_x(999); class BC 2{ d 1. BC 1: : set_x(111); private: d 1. BC 2: : set_x(222); int x; } public: void set_x(int a){x=a; } };
BC 1 3 多继承 BC 2 d 1 - int x BC 1: : x 111 + set_x +set_x BC 2: : x 222 + DC d 1; BC 1 X int x + set_x BC 2 d 1. set_x(999); × d 1. BC 1: : set_x(111); d 1. BC 2: : set_x(222);
class BC 1{ class DC: public BC 1, public BC 2 private: {private: int x; public: void set_x(int a){x=a; } }; class BC 2{ int main() private: {DC d 1; int x; d 1. set_x(999); public: d 1. BC 1: : set_x(111); void set_x(int a){x=a; } d 1. BC 2: : set_x(222); } 例4. 4_163
BC 1 - int x + set_x + BC 1 d 1 BC 2 DC + X int x + set_x 支配规则 - int x + set_x BC 1: : x 111 BC 2: : x 222 DC: : x 999 DC d 1; BC 2 d 1. set_x(999); d 1. BC 1: : set_x(111); 支配规则 d 1. BC 2: : set_x(222);
class BC{ {DC z; public: int x; z. DC 1: : x=1; }; z. DC 2: : x=2; class DC 1: public BC{ cout<<z. DC 1: : x<<endl; }; cout<<z. DC 2: : x<<endl; class DC 2: public BC{ } }; class Z: public DC 1, public DC 2 {} int main() 1 2 构造函数顺序:BC, DC 1, BC, DC 2, z 例 4. 4_164_2
BC Z z; + int x DC 1 + DC 2 + + int x × z. x=1; + int x z. BC: : x=1; × z. DC 1: : x=1; z. DC 2: : x=2; + + int x Z + int x z + DC 1: : x 1 DC 2: : x 2 二 义 性
class BC{ {DC z; public: int x; z. DC 1: : x=1; }; z. DC 2: : x=2; class DC 1: public virtual BC{ cout<<z. DC 1: : x<<endl; }; cout<<z. DC 2: : x<<endl; class DC 2: virtual public BC{ } }; class Z: public DC 1, public DC 2 {} 2 2 int main() 构造函数顺序:BC, DC 1, DC 2, z 例 4. 4_164_2
BC Z z; + int x DC 1 + + int x + z. x=3; + DC 2 + int x Z √ z. BC: : x=4; √ z. DC 1: : x=1; √ z. DC 2: : x=2; √ + z + int x DC 1: : x DC 2: : x 3412
11. 2. 1 编译时刻的多态性 函数重载为一种常见的编译时刻多态性,编译时通过参数类型匹配,定 位所调用函数的具体实现,然后用该实现代码调用代替源程序中的函数 调用。 [例11. 9] 编译时刻多态性。 #include "iostream. h" const float PI=float(3. 14); class CPoint { private: int m_x; int m_y; public: CPoint(int x=0, int y=0); void Area() { cout<<"Here is a point's area: " <<0<<endl; } }; CPoint: : CPoint(int x, int y) { m_x=x; m_y=y; } class CCircle : public CPoint { private: float m_n. Radius; public: CCircle(int x=0, int y=0, float r=0) : CPoint(x, y) { m_n. Radius=r; } void Set. Radius(float r) { m_n. Radius=r; } void Area() { cout<<"Here is a circle's area: " <<PI*m_n. Radius<<endl; } }; void main() { CCircle c 1; c 1. Area(); } 至 11. 2
class Base{ public: void who() void main() { Base base_obj; Base *p; {cout<<"base"<<endl; } Firstderived first_obj; }; Secondderived second_obj; class Firstderived: public Base p=&base_obj; {public: void who() p->who(); {cout<<"Firstderived"<<endl; } p=&first_obj; }; p->who(); class Secondderived: public Base p=&second_obj; {public: void who() {cout<<"Secondderived"<<endl; } }; p->who(); } 例5. 1_1
base Base + who Firstderived Secondderived + void who() √ + void who() √
class Base{ public: virtual void who() void main() { Base base_obj; Base *p; {cout<<"base"<<endl; } Firstderived first_obj; }; Secondderived second_obj class Firstderived: public Base p=&base_obj; {public: virtual void who() p->who(); {cout<<"Firstderived"<<endl; } p=&first_obj; }; p->who(); class Secondderived: public Base p=&second_obj; {public: virtual void who() {cout<<"Secondderived"<<endl; } }; p->who(); } 例5. 1_2
Base v + who Firstderived base Firstderived Secondderived + void who() √
VTABLE Base 1000 Base: : who( ) 100 V + who Secondderived Firstderived + void who() √ 2000 VTABLE Firstderived: : who( ) 3000 200 VTABLE Secondderived: : who( ) 300
Base base_obj p->who() VTABLE vptr 1000 2000 100 Firstderived first_obj p->who() Base: : who( ) 2000 VTABLE Firstderived: : who( ) 200 Second_obj Secondderived p->who() vptr 1000 3000 VTABLE Secondderived: : who( ) 300
11. 2. 3 虚函数 虚析构函数可以被说明为虚函数,利用虚析构函数,删除对象时不必考虑对 象的类型(父类或子类),虚函数机制将保证调用适当的析构函数。 #include "iostream. h" #include "string. h" class CBase { public: virtual ~CBase() { cout<<"CBase: : ~CBase()"; } }; class CDerived : public CBase { public: virtual ~CDerived() { cout<<"CDerived: : ~CDerived()"<<endl; } }; void main() { CBase* p. B=new CDerived; delete p. B; }
#include <iostream. h> #include <string. h> #include <conio. h> class TPerson { private: char *name; public: TPerson(const char *s) { name=new char[strlen(s)+1]; strcpy(name, s); } virtual void print() { cout<<name<<endl; } virtual ~TPerson() { delete [ ] name; } }; 例5. 1_3
class TStudent: public TPerson { private: char *major; public: TStudent(const char *n, const char *m) : TPerson(n) { major=new char[strlen(m)+1]; strcpy(major, m); } virtual void print(){TPerson: : print(); cout<<major<<endl; } ~TStudent() { delete[ ] major; } }; void main() { TPerson *p=new TStudent("Zhang", "Computer"); p->print(); delete p; //TStudent: : ~TStudent被调用 getch(); }
VTABLE TPerson 1000 * name; Tperson: : print( ) Tperson: : ~ TPerson(const char *s) V void print( ) V ~TPerson( ) TStudent VTABLE 2000 * name; * major; Tstudent: : print( ) V void print( ) TStudent(s, m) Tstudent: : ~ V void print( ) V ~TPerson( )
VTABLE 1000 name zhang Tperson: : ~ 1000 p delete p Tperson: : print( ) major computer vptr 2000 VTABLE 2000 Tstudent: : print( ) Tstudent: : ~
VTABLE 1000 name=zhang Tperson: : print( ) 1000 major=computer p delete p vptr=2000 VTABLE 2000 Tstudent: : print( ) 内存遗漏问题
求平面图形的面积 #include <iostream> using namespace std; class Shape { protected: int a, b; public: void set(int i, int j=0) { a=i; b=j; } virtual void print_area(void)=0; //纯虚函数 }; class triangle: public Shape { public: virtual void print_area(void) { cout<<"n triangle with height "; cout<<a<<" and base "<<b; cout<<" has an area of "; cout<<a*b/2; } }; 例5. 3_shape
class circle: public Shape { public: virtual void print_area(void) { cout<<"n Circle with radius "<<a; cout<<" has an area of "; cout<<3. 14*a*a; } }; class rectangle: public Shape { public: virtual void print_area(void) { cout<<"n rectangle with legnth "<<a; cout<<" and width "<<b<<" has an area of "; cout<<a*b<<"n"; } };
int main(void) { Shape *p; triangle t; circle c; rectangle r; } p=&t; p->set(10, 16); p->print_area(); p=&c; p->set(100); p->print_area(); p=&r; p->set(10, 160); p->print_area(); triangle with height 10 and base 16 has an area of 80 Circle with radius 100 has an area of 31400 rectangle with legnth 10 and width 160 has an area of 1600
shape # a, b + set(…) + print_area()=0 triangle circle rectangle # a, b + set(…) + print_area()=0 + print_area()
int main(){ class B{ B* p; D d; public: void m(int x){cout<<"B: : m()"<<endl; } }; 遮 蔽 class D: public B{ public: void m(){cout<<"D: : m()"<<endl; } }; p=new D; p->m(); × p->m(3); 编 译 期 d. m(3); × 绑 d. B: : m(3); 定 d. m(); 例5. 2_3
int main(){ class B{ public: B* p; D d; virtual void m(int x){cout<<"B: : m()"<<endl; } p=new D; }; p->m(); × 遮 蔽 class D: public B{ public: virtual void m(){cout<<"D: : m()"<<endl; } }; 例5. 2_4 p->m(3); 编 译 期 d. m(3); × 绑 d. B: : m(3); 定 d. m();
int main(){ class B{ public: B* p; D d; virtual void m(){cout<<"B: : m()"<<endl; } p=new D; }; p->m(); 覆 盖 class D: public B{ public: virtual void m(){cout<<"D: : m()"<<endl; } }; //运行期绑定 d. B: : m(); d. m(); 编 译 期 绑 定
11. 3 整体—部分关系的实现 C++对整体—部分关系提供支持手段,对复合聚合,采用嵌入式对象的方 式,即属性的类型为类,例如消息窗口类可以如下定义: class CButton { … CButton() { …… } … }; class CIcon { … CIcon() { …… } … }; class CStudent { … CStudent(const char* p. Student. Name) {…} … }; class CGroup { private: CStudent* m_p. Students; int m_n. Group. ID; … CClass 班号:int m_n. Class. ID 学生:CStudent* m_p. Students. . . 设 置 学 生 :Set. Student(CStudent*) 构造空班n. ID :CClass(int n. ID). . . CClass 组号:int m_n. Group. ID 学生:CStudent* m_p. Students. . . 设 置 学 生 :Set. Student(CStudent*) 构造空组n. ID :CGroup(int n. ID). . . 25 班级成员 CStudent. . . 小组成员 5
public: void Set. Student(CStudent* p. Students) { m_p. Student=p. Student; } CGroup(int n. ID) { m_n. Group. ID=n. ID; m_p. Students=new CStudnet[5]; … //小组由 5名学生组成 } … }; class CClass { private: CStudent* m_p. Students; int m_n. Class. ID; … public: CClass(int n. ID) { m_n. Class. ID=n. ID; m_p. Students=new CStudnet[35]; //班级由 35名学生组成 … }
CStudent* Get. Student() { return m_p. Students; } void Set. Student(CStudent* p. Students) { m_p. Student=p. Student; } …… }; void main() { CStudent the. Whole[2550]={ CStudent("Marry"), … , CStudent("Tom") }; CClass My. Class 3(3); //成立班级,但具体由哪些学生组成尚未确定 My. Class 3. Set. Student((the. Whole+70)); //本班学生由学校学生名册中第 71位开始的35人组成 CGroup 6(6); Goup 6. Set. Student((My. Class 3. Get. Student()+25)); //第 6学习小组由班级学生名册中第 26名开始的5个人组成 … } 至 第 11章
- Slides: 77