面向对象c++之继承
来源:互联网 发布:大学网络课程网站 编辑:程序博客网 时间:2024/06/16 21:30
面向对象三大机制包括:
1.封装,隐藏内部实现。
2.继承,复用现有代码。(面向对象最显著的特征)
3.多态,改写对象行为。
继承,是一种复用的手段。是从先辈处得到属性和行为特征。类的继承就是新的类从已
有的类那里得到已有的特征。
类成员的访问限定有三种:public,protected,private,在类外可以访问类的公有成员,
私有和保护都不可以访问。代码举例:
#include<iostream>using namespace std;class A{public:A():_pub(1),_pro(2),_pri(3){}public:int _pub;protected:int _pro;private:int _pri;};int main(){A a;cout << a._pub << endl;cout << a._pro << endl;cout << a._pri << endl;system("pause");return 0;}
代码编译不通过,提示不可访问类的私有和保护成员。
也有3种继承关系:public(公有继承),protected(保护继承),private(私有继承)
那么父类成员在子类中的访问属性究竟会是怎样的呢?
【总结】在继承机制下,无论哪种继承方式,子类中可以访问父类的公有保护成员,
私有成员不可访问;在类外,只能访问公有成员,私有和保护都不可访问。这个可以通
过代码去验证。
类外只能访问类的公有成员。如果一些父类成员不想被父类对象直接访问,但是需
要在派生类中访问,就定义成保护成员。protected成员的特点:“外人”不可访问,“儿
子”可以访问。
class中继承方式默认是private,struct中默认是public。
类与类之间的关系有三种:
1.has-a,一个类的成员是另一个类的对象;私有继承是另一种实现has-a的途径。
2.uses-a,一个类的成员函数的参数是另一个类的对象
3.is-a,公有继承,父类可用的成员对子类也是可用的。
赋值兼容规则:
前提:public继承下。
1.父类对象 = 子类对象
举例:人通过继承得到超人,即超人具备人的特性,当然也有其本身特有的功能。
人 = 超人(超人的特异功能不被赋值)
2.父类对象不可赋值给子类对象。
3.父类指针可以指向子类对象,如图。子类指针不可以指向父类对象。但是可以通过
强制类型转换完成。但是也可能会出现一定的问题。(下边的代码)
4.父类对象的引用可以引用子类对象。(与指针同理)
class B{public:B():_pub(10), _pro(20), _pri(30){cout << "B()" << endl;}void show(){cout << _pub << endl;cout << _pro << endl;cout << _pri << endl;}public:int _pub;protected:int _pro;private:int _pri;};class D:public B{public:D():B() ,_i(100){cout << "D()" << endl;}void show(int ){cout << _pub << endl;cout << _pro << endl;//cout << _pri << endl;}int _i;};int main(){D d;B b; D *pd;pd = (D *)&b;//子类对象通过强转指向父类对象pd->_i = 10; system("pause");return 0;}
运行之后会出现程序崩溃。所以尽量不要强转。
注:创建子类对象时,会先调用父类的构造函数,然后再调用子类的构造函数,结束
时,先调用子类的析构函数,再调用父类的析构函数。若父类没有默认的构造函数,子
类构造函数中对父类成员的初始化必须在初始化列表中实现。
如果子类中有与父类同名的函数或者成员,父类的函数或者成员被隐藏,与函数的参
数,返回值类型都无关。隐藏,父类的函数仍然存在。
举例:
class B{public:B():_b(1){}void Show(){cout << _b << endl;}private:int _b;};class D:public B{public:D():B(),_b(2),_d(3){}void Show(){cout << _b << endl;cout << _d << endl;}private:int _b;int _d;};int main(){B b;D d;b.Show();d.Show();cout << sizeof(b) << endl;cout << sizeof(d) << endl;system("pause");return 0;}
D中有与B同名的成员和函数,所以子类中就会隐藏父类的成员,但是父类的成员依然存
在,b.Show()依然可以打印出B中的成员。b的大小是4字节,d的大小是12字节。这就是
所谓的隐藏。
多重继承:
前边整理的都是都是单继承,即一个类从一个父类派生而来。当一个子类有多个父类
时,这种继承方式成为多重继承。
在多重继承中,最典型的继承方式就是菱形继承。
为了解决菱形继承中出现的问题,我们引入了虚基类。看下边的代码:
class A{public:A():_a(1){}protected:int _a;};class B :virtual public A{public:B():_b(2){}protected:int _b;};class C :virtual public A{public:C():_c(3){}protected:int _c;};class D :public B, public C{public:D():_d(4){}protected:int _d;};int main(){D d;cout << sizeof(d) << endl;system("pause");return 0;}
要是没有在B,C的派生列表中加上virtual关键字,最终输出d的大小是20字节,加上之
后呢就是24字节。
我们知道,如果是单继承的话,子类成员在内存中的情况就是:先是来自父类的成员,
然后就是来自子类的成员,紧挨存储。那么虚继承的对象模型究竟是什么,打开内存看
一下:(windows下的情况)linux下的情况之后补充 。
大家也可以打开内存看单继承和菱形继承的对象模型,这里就不给出了。
友元与继承:
由于友元不可以传递,所以友元就不能继承。父类的友元不可以访问子类的私有和保
护成员,但是可以访问子类从父类继承下来的成员。父类的友元要想访问子类,必须将
该友元声明为子类的友元。
class D;class B{friend void Show(B &b,D &d);public:B():_b(1){}protected:int _b;};class D:public B{public:D():_d(4),_e(5),_f(6){}public:int _d;protected:int _e;private:int _f;};void Show(B &b, D &d){cout << b._b << endl;cout << d._b << endl;cout << d._d << endl;//cout << d._e << endl;//cout << d._f << endl;}int main(){B b;D d;Show(b,d);system("pause");return 0;}
父类的友元函数并不能访问子类的私有成员和保护成员。
静态成员与继承:
如果父类定义了一个静态成员,则在整个继承体系中都只有该成员的唯一定义,不管
从父类派生出多少子类,对于每个静态成员来说只存在唯一的实例。并且子类的对象都
能访问父类的静态成员。这里就不给出代码了,感兴趣的可以自己写出代码。
以上问题如有不合理的地方,希望联系1521107105@qq.com,不胜感激~
- 【C#】面向对象之继承
- 用C实现面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- 面向对象之继承
- C 语言面向对象-- 继承
- C语言实现面向对象之继承性
- kobject引用计数
- 姿势跑法
- 成为Java顶尖程序员 ,看这11本书就够了
- Ubuntu 命令解释
- 缓冲池的概念
- 面向对象c++之继承
- java关键字之super
- Matlab问答day6
- jQuery源码研究分析学习笔记-jQuery.deferred()(12)
- POJ2635——The Embarrassed Cryptographer
- Redis入门很简单之一【简介与环境搭建】
- Redis入门很简单之二【常见操作命令】
- uva11732 "strcmp()" Anyone?
- 从零基础接触java第六周第一节