C++ Primer Plus读书笔记07

2012-03-05

1、在类声明中声明的结构、类或枚举,作用域为整个类。此时不创建对象;若为private    权限,只能在类中使用被声明的类型;若public,则可在类外面使用被声明的类型

2、派生类的构造函数

       (1)先创建基类对象→通过成员初始化列表将基类信息传给基类构造函数

       (2)若不使用初始化列表,系统将调用基类的默认构造函数

       (1)derived::derived(int x,int y):base(x,y)

              {……}

       (2)derived::derived(int x,int y)

              {……}//此法调用基类的默认构造函数

       析构的顺序相反,先析构派生类,再析构基类

3、基类指针可以指向派生类对象,基类引用可以引用派生类对象(无需类型转换)

       但只能调用基类方法,不可用派生类的

4、多态:同一个方法在派生类和基类的行为不同,即方法的行为取决于调用该方法的对象

       在基类中:virtual void func()    在派生类中: virtual void func()

       当通过对象调用时,不加virtual也可;当通过指针或引用调用时,若不加virtual,程序根据引用或指针的类型选择方法,若加了virtual,程序根据引用或指针指向的对象的类型选择方法

例: Base s1;  derived s2;    base &p1=s1;       base &p2=s2;

若不加virtual,p1.func与p2.func均调用base::func

若添加virtual,p1,func调用base的,p2.func调用derived的

注:同时为基类声明一个虚析构函数 virtual ~base();

用处:假设有多个实例,分别为basederived类型,则不可用数组来存(类型不同),但可用一个指向base的指针数组,这些指针可以分别指向basederived对象,此时就必须用虚函数——多态

5、动态、静态联编     向上、向下转换P447-P448

6、构造函数不能是虚函数,析构函数应当是虚函数,即使他不执行任何操作

       eg:Base *p=new derived;   delete p;

       若不virtual,则只调用了base的析构,不会释放derived指向的内存;所以用虚函数,先析构derived(),再析构base();

       另,给类定义一个虚拟析构函数,即使这个类不用做基类。

       只有类成员才能是虚函数,友元不能是虚函数

7、A→B→C(箭头对应派生关系)

       若C没有重新定义虚函数,用B的版本,若B没有定义,用A的版本

       特例:若A:virtual void func(int a)const;  //const表示不会修改内容

              B:virtual void func() const;

              特征标不一样时,将把A隐藏(而不是重载),此时B类不可以用A版本的函数

       所以,(1)虚函数应保证特征标相同(返回值可以不一样)

              (2)若A中func()有多个重载,则应在派生类中重新定义所有的基类版本

8、protected:       A→B      A中:protected int m;

       对A而言,protected相当于private,对B而言,protected相当于public

       ∴数据成员最好不用protected,否则派生类对想可能会修改

2012-03-07

1、valarray类 include<valarray>     //类比vector

       double data[5]={1,2,3,4,5};

       valarray<int > v1(8);    //v1长度为8

       valarray<int >v2(10,8);       //8个10

       valarray<double>v3(data,4);      //以data 前四个初始化

2、class Student{

       private:   string name; 

       valarray<double>scores;

       }      //通过包含对象成员的类实现has a 关系(法一)

       //成员函数可以使用string 和valarray的接口,但在类外不能用name.size()之类

       //获得了实现,但没有继承接口  ∴这叫组合

3、使用explicit防止单参数构造函数的隐式转换

       使用const限制方法修改数据

4、公有继承 is a 关系

       私有继承 has a关系//获得实现,没有继承接口:类的公有方法成为派生类的私有方法

       通过私有继承实现has a关系(法二)

       class sutdent:private string,private valarray<double>

{……

}

访问基类方法:(类内)

对于法一,通过对象名来调用基类方法

对于法二,通过类名和作用域解析符调用方法

法一中,score.size();

法二中,只能用valarray<double>::size();

访问基类对象:强制类型转换

建议用包含(法一),而不是私有继承(法二),建立has a关系

5、共有多继承,来表示is a关系(必须显式声明为public,因为默认是private)

假设从上至下分别为类ABCD,继承关系如图

       则当D d;时,d中包含2个A对象(一个B包含的,一个C包含的)

       ∴虚基类 从多个类(他们基类相同)派生出来的对象只继承一个基类对象

       class B:virtual public A{……}

       class C:virtual public A{……}

       则class D:public B,public C{……}正确,当创建D类的对象时只会创建一次A

 

       此时,D的构造函数将使用新规则

       原规则:D(参数列表):B(a,b),C(a,b,){……}     //错

       新规则:D(参数列表):A(a),B(a,b),C(a,b){……}     //显式的调用基类(虚基类)A

 

       方法使用:

       D d;        d.show();             //错,不知道是用B的还是C的

       法一:           d.B::show();

       法二:在D中重新定义show()

       void D::show()

       {      B::show();

}

原文地址:https://www.cnblogs.com/yangtianxing/p/2435024.html