新标准C++程序设计读书笔记_继承和多态

简单继承的例子:

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4
 5 class CStudent
 6 {
 7 private:
 8     string name;
 9     string id; //学号
10     char gender; //性别,‘F‘代表女, ‘M‘代表男
11     int age;
12 public:
13     void PrintInfo();
14     void SetInfo( const string & name_,const string & id_,
15     int age_, char gender_ );
16     string GetName() { return name; }
17 };
18
19 void CStudent::PrintInfo()
20 {
21     cout << "Name:" << name << endl;
22     cout << "ID:" << id << endl;
23     cout << "Age:" << age << endl;
24     cout << "Gender:" << gender << endl;
25 }
26
27 void CStudent::SetInfo( const string & name_,const string & id_,
28 int age_,char gender_ )
29 {
30     name = name_;
31     id = id_;
32     age = age_;
33     gender = gender_;
34 }
35
36 class CUndergraduateStudent : public CStudent
37 {
38 //本科生类,继承了CStudent类
39 private:
40     string department; //学生所属的系的名称
41 public:
42     void QualifiedForBaoyan()
43     {
44         //给予保研资格
45         cout << “qualified for baoyan” << endl;
46     }
47
48     void PrintInfo()
49     {
50         CStudent::PrintInfo(); //调用基类的PrintInfo
51         cout << “Department:” << department <<endl;
52     }
53
54     void SetInfo( const string & name_,const string & id_,
55     int age_,char gender_ ,const string & department_)
56     {
57         CStudent::SetInfo(name_,id_,age_,gender_); //调用基类的SetInfo
58         department = department_;
59     }
60 };
61
62 int main()
63 {
64     CUndergraduateStudent s2;
65     s2.SetInfo(“Harry Potter ”, “118829212”,19,‘M’,“Computer Science”);
66     cout << s2.GetName() << “ ” ;
67     s2.QualifiedForBaoyan ();
68     s2.PrintInfo ();
69     return 0;
70 }

类之间的两种关系
(1)继承:“是”关系。
基类 A, B是基类A的派生类。逻辑上要求:“一个B对象也是一个A对象”。
(2)复合:“有”关系。
类C中“有” 成员变量k, k是类D的对象,则C和D是复合关系,一般逻辑上要求:“ D对象是C对象的固有属性或组成部分”。

几何形体程序中,需要写“点”类,也需要写“圆”类

1 class CPoint
2 {
3     double x,y;
4 };
5
6 class CCircle : public CPoint
7 {
8     double r;
9 };

这是不合理的,应该使用复合关系;每一个“圆”对象里都包含(有)一个“点”对象,这个“点”对象就是圆心

 1 class CPoint
 2 {
 3     double x,y;
 4     //便于Ccirle类操作其圆心
 5     friend class CCircle;
 6 };
 7
 8 class CCircle
 9 {
10     double r;
11     CPoint center;
12 };

覆盖
派生类可以定义一个和基类成员同名的成员,这叫覆盖。在派生类中访问这类成员时,缺省的情况是访问派生类中定义的成员。要在派生类中访问由基类定义的同名成员时,要使用作用域符号“::”

访问控制符

以下均表示可以被下列函数访问

1、基类的private成员:
(1)基类的成员函数
(2)基类的友员函数

2、基类的public成员:
(1)基类的成员函数
(2)基类的友员函数
(3)派生类的成员函数
(4)派生类的友员函数
(5)其他的函数

3、基类的protected成员:
(1)基类的成员函数
(2)基类的友员函数
(3)派生类的成员函数可以访问当前对象的基类的保护成员

 1 class Father
 2 {
 3 private:
 4     int nPrivate; //私有成员
 5 public:
 6     int nPublic; //公有成员
 7 protected:
 8     int nProtected; // 保护成员
 9 };
10
11 class Son : public Father
12 {
13     void AccessFather ()
14     {
15         nPublic = 1; // ok;
16         nPrivate = 1; // wrong
17         nProtected = 1; // OK,访问从基类继承的protected成员
18         Son f;
19         f.nProtected = 1; //wrong ,f不是当前对象
20     }
21 };
22
23 int main()
24 {
25     Father f;
26     Son s;
27     f.nPublic = 1; // Ok
28     s.nPublic = 1; // Ok
29     f.nProtected = 1; // error
30     f.nPrivate = 1; // error
31     s.nProtected = 1; //error
32     s.nPrivate = 1; // error
33     return 0;
34 }

派生类的构造函数

在创建派生类的对象时,需要调用基类的构造函数:初始化派生类对象中从基类继承的成员。在执行一个派生类的构造函数之前,总是先执行基类的构造函数。

调用基类构造函数的两种方式
(1)显式方式:在派生类的构造函数中,为基类的构造函数提供参数.derived::derived(arg_derived-list):base(arg_base-list)
(2)隐式方式:在派生类的构造函数中,省略基类构造函数时,派生类的构造函数则自动调用基类的默认构造函数.

派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数。

在创建派生类的对象时:
(1)先执行基类的构造函数,用以初始化派生类对象中从基类继承的成员;
(2)再执行成员对象类的构造函数,用以初始化派生类对象中成员对象。
(3)最后执行派生类自己的构造函数

在派生类对象消亡时:
(1)先执行派生类自己的析构函数
(2)再依次执行各成员对象类的析构函数
(3)最后执行基类的析构函数
析构函数的调用顺序与构造函数的调用顺序相反。

赋值规则

(1)派生类的对象可以赋值给基类对象
b = d;
(2)派生类对象可以初始化基类引用
base & br = d;
(3)派生类对象的地址可以赋值给基类指针
base * pb = & d;
如果派生方式是 private或protected,则上述三条不可行。

公有派生的情况下,派生类对象的指针可以直接赋值给基类指针
Base * ptrBase = &objDerived;
(1)ptrBase指向的是一个Derived类的对象;
*ptrBase可以看作一个Base类的对象,访问它的public成员直接通过ptrBase即可,但不能通过ptrBase访问objDerived对象中属于Derived类而不属于Base类的成员
(2)即便基类指针指向的是一个派生类的对象,也不能通过基类指针访问基类没有,而派生类中有的成员。
(3)通过强制指针类型转换,可以把ptrBase转换成Derived类的指针
Base * ptrBase = &objDerived;
Derived *ptrDerived = (Derived * ) ptrBase;
要保证ptrBase指向的是一个Derived类的对象,否则很容易会出错。

时间: 2024-08-14 07:14:52

新标准C++程序设计读书笔记_继承和多态的相关文章

新标准C++程序设计读书笔记_运算符重载

形式 返回值类型 operator 运算符(形参表) { …… } 运算符重载 (1)运算符重载的实质是函数重载(2)可以重载为普通函数,也可以重载为成员函数 1 class Complex 2 { 3 public: 4 double real,imag; 5 Complex( double r = 0.0, double i= 0.0 ):real(r),imag(i) { } 6 Complex operator-(const Complex & c); 7 }; 8 9 Complex

新标准C++程序设计读书笔记_类和对象

面向对象的程序设计方法 抽象:将某类客观事物共同特点(属性)归纳出来,形成一个数据结构(可以用多个变量描述事物的属性):将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构. 封装:通过某种语法形式,将数据结构和操作该数据结构的函数“捆绑”在一起,形成一个“ 类”,从而使得数据结构和操作该数据结构的算法呈现出显而易见的紧密关系. 从客观事物抽象出类 写一个程序,输入矩形的长和宽,输出面积和周长. 比如对于“矩形”这种东西,要用一个类来表示,该如何做“抽象”呢?矩形的属

《Head First Java》读书笔记——7 继承与多态

(一)继承范例 1.范例一: 1 pulic class Doctor{ 2 boolean worksAtHospital; 3 void treatPatient(){ 4 //执行检查 5 } 6 } 7 public class FamilyDoctor extends Doctor{ 8 boolean makesHouseCalls; 9 void giveAdvice(){ 10 //提出诊断 11 } 12 } 13 public class Surgeon extends Do

汇编语言程序设计读书笔记(3)- 程序范例

主要描述三方面的内容:第一是汇编语言的程序模版,以及模版涉及到的一些知识点:第二是如何调试汇编语言:第三是如何在汇编语言中调用C库函数. 1. 汇编语言的组成 汇编语言由段(section)组成,一个程序中执行的代码,叫文本段(text),程序还可能有定义变量,有付给初始值的变量放在数据段(data)中,没有赋初值或者付给零初值的放在bss段中.text段一定是要有的,data和bss可以没有. 2. 段的定义 用.section语法定义段.比如: .section .text定义文本段, .s

《循序渐进DB2.DBA系统管理、运维与应用案例》(牛新庄著)读书笔记2

<循序渐进DB2.DBA系统管理.运维与应用案例>(牛新庄著)读书笔记2                                              Windows下的DB2向导安装 现在的DB2已经支持了广泛的IT基础设施,可以在众多平台上运行.Windows.Linux.UNIX这三种平台统称为luw平台.对于自学DB2的人而言,由于不可能自己购买大型机或高端的服务器,所以更多的是把DB2装在luw平台上进行练习.而如果想要尽可能的贴近真实的生产环境,为日后工作打基础,最好是

C++旧源码向新标准移植陷井(一)_局部栈变量的生命周期

之前在VC++6.0上面写了下面这样的代码: int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; //不重要的部分略过if (argc>1) {if (strcmp(argv[1],"createpcsstep") == 0) { CDlgCreateStepPcs dlg; dlg.DoModal(); break; } else if (strcmp(argv[1],"clea

多态实现的原理------新标准c++程序设计

"多态"的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespace std; class A{ public: int i; virtual void func(){}; virtual void func2(){}; //如果为只有一个去掉 virtual 关键字即virtual void func2(){};变为 void func2(){}; 输

JavaScript 面向对象程序设计(下)&mdash;&mdash;继承与多态 【转】

JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论一下面向对象程序设计中的另外两个要素:继承与多态. 1 又是几个基本概念 为什么要说又呢? 在讨论继承时,我们已经列出了一些基本概念了,那些概念是跟封装密切相关的概念,今天我们要讨论的基本概念,主要是跟继承与多态相关的,但是它们跟封装也有一些联系. 1.1 定义和赋值 变量定义是指用 var a;

读书笔记_《50 Android Hacks》之一 linearlayout的weightsum及weights

最近在读<50 Android Hacks>,准备谢谢读书笔记,并不断丰满一下. 听到过这样的问题,“如果我想让一个button占父控件的50%,应该怎么办”. 通常来说,我们可以使用linearlayout其中的属性  android:layout_weight属性 在实现方法上来说,有几种方法来实现. android的设备有不同的size,对于不同的屏幕尺寸,我们应该有一种普遍 适用的方法. 我们可以使用layout_weight以及weightSum属性来填满layout的剩余空间. 其