c++继承上

一、继承顾名思义就是儿子和父亲的关系,先回顾一下它的定义:

1.一个类A可以继承另一个类B,那么我们说类B是基类(父类),类A为派生类(子类)。

2.子类从父类继承了所有成员,除了构造函数,析构函数,赋值元素安抚重载函数。

3.子类继承父类后,子类成员分两部分,1.继承父类的部分,2.子类自己扩展的成员。

4.虽然父类的私有成员被子类继承,但子类依然不能直接访问这些私有成员,子类只能通过继承自父类的公有的继承函数来访问。


二、继承方式:

继承方式有三种:

1.公有继承:写法:class T : public D 子类 T公有继承于父类D。

     原理:父类里的公有成员(包括成员变量和函数),子类继承过来还是公有的,父类受保护的成员继承过来还是受保护    的成员,私有的继承过来还是私有的。


2.私有继承:写法:class T : private D 子类 T公有继承于父类D。

     原理:父类里的公有成员(包括成员变量和函数),子类继承过来变成私有的,父类受保护的成员继承过来变成私有    的成员,私有的继承过来还是私有的。

3.受保护继承:写法:class T : private D 子类 T公有继承于父类D。(在类外受保护成员不能访问,但在继承子类中可以访问)

         原理:父类里的公有成员(包括成员变量和函数),子类继承过来变成私有的,父类受保护的成员继承过来变成私有           的成员,私有的继承过来还是私有的。


总结:继承方式的权限只能缩小不能放大,例如:私有成员,你继承过来还是私有的,权限不能放大。


三、用子类对象初始化父类对象

有三种:

1.对象赋值
<span style="font-size:14px;">  Drived d;
  Base b;
  b=d;</span>
   把等号有右边的子类对象,赋值给等号左边的父类对象时,仅仅是把子类中来自于父类的那一部分成员,赋值给等号左边的父类对象,而赋值完成后,等号左边的对象,依然是父类的对象,依然是父类对象。(初始化父类,就是把两者公共的部分成员赋值给父类,左边的是父类还是父类)


2.引用赋值
   
<span style="font-size:14px;">Derived d;
Base &b=d;
Derived::func();
d.func();//错误
b.func();//不能使用父类引用调用子类扩展成员</span>
  
把等号右边的子类对象,赋值给等号左边的父类的引用,直接初始化了父类的引用,虽然父类引用了子类对象,但该对象(b)调用该方法(子类继承父类的方法)还是父类的方法。如果不懂,下边有这方面的讲解。还有一点是:父类引用不能调用子类的所扩展的方法。例如:当b调用func()方法会出错,因为b是父类的引用,父类没有这个方法,会出错(尽管它引用了子类对象)。

3.指针赋值
<span style="font-size:14px;">Derived d;
Base *b=&d;
Drived::func(){};
d.func();//正确
b->func();//错误</span>


  把等号右边的子类对象的地址,赋值给等号左边的父类的指针,直接初始化了父类的指针,这个和上边的引用类似,直接看例子,父类指针b指向了子类的对象,调用的时候,子类对象可以调用子类扩展的函数,而父类指针调用子类扩展的函数则会出错(原因还是因为父类地没有这个方法,尽管它的指针指向了子类对象)。

补充:

当然如果你想通过父类访问子类扩展的也可以,那就必须强转了。
Base * b=new Derived;
Derived::func(){};
//b->func(); error
((Deriverd*)b)->func();//ok, 强制转化

    如果父类指针指向子类对象,需要把父类的指针转化为指向子类对象的指针,来访问子类扩展成员这就是所谓的向下转。但是,向下转型是危险的,因为父类指针有可能没有指向子类对象。

总结:如果一个函数是覆盖类型的(子类父类都有这个函数),那么谁调用它,就是谁的,和指针指向无关(父类指针如果指向子类对象,那么这个指针调用这个函数,也还是父类的,主要看前边(看赋值左边,不看右边));

四、构造函数和析构函数

简答两句话:

构造子类时,先执行父类的构造函数,然后执行子类的构造函数。(创建子类对象时)

析构子类时,先执行子类的析构函数,然后执行父类的析构函数。(结束时)


下一篇 :讲多继承和虚函数

posted on 2016-08-17 19:10  游戏爱好者  阅读(234)  评论(0编辑  收藏  举报

导航