面向对象程序设计的核心思想是数据抽象(类的接口与实现分离)、继承和动态绑定

基类

虚函数:基类希望派生类各自定义适合自身的版本的函数

在c++中,当我们使用基类的引用或指针调用虚函数时将发生动态绑定。

基类通常都应该定义一个虚析构函数。C++规定:用不带有虚析构函数的基类的指针来删除一个派生类对象(基类指针指向派生类对象,delete该指针),这个对象的派生类部分没有被析构,造成内存泄漏。

注意:

1.应该为多态基类声明虚拟析构函数。如果一个类有一个虚函数,那么它也应该有一个虚析构函数

2.如果一个类不是被设计为基类或者它们并不是按照多态的方式来使用的(不是用基类指针或引用来指向派生类对象),不要为它们声明虚析构函数 ,vptr及virtual table的存在使得内存空间浪费

任何构造函数之外的非静态函数都可以是虚函数,virtual只能出现在类内部的声明语句之前而不能用于类外部的函数定义。如果基类把一个函数声明成虚函数,则该函数在派生类中隐式地也是虚函数。

构造函数不能是虚函数的原因:

1.从存储空间角度

  如果构造函数是虚函数,就需要通过 vptr来调用,vptr是存储在对象的内存空间中,可是对象还没有实例化,也就是内存空间还没有,怎么找vptr呢?所以构造函数不能是虚函数。

2.从使用角度来看

虚函数作用是通过父类的指针或引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数

static函数不能是虚函数的原因:

调用虚函数需要类的实例,static函数作为类函数,不属于类的实例,自然无法实现多态了。

派生类

派生类能访问public protected成员,不能访问private成员。

如果派生类没有覆盖其基类中的某个虚函数,则该虚函数的行为类似其他的普通成员,派生类会直接继承其在基类中的版本。c++11允许派生类显式地注明它使用某个成员函数覆盖了它继承的虚函数,在声明语句的最后添加override.

派生类必须使用基类的构造函数来初始化它的基类部分,通过构造函数初始化列表将实参传递给基类构造函数(否则使用默认构造函数)。首先初始化基类的部分,然后按照声明的顺序依次初始化派生类的成员。

派生类的声明包含类名但是不包含它的派生列表,派生列表必须与类的主体一起出现。

如果我们想将某个类用作基类,则该类必须已经定义而非仅仅声明。派生类中包含并且可以使用它从基类继承而来的成员,为了使用这些成员,派生类需要知道它们是什么,因此一个类不能派生它本身。vs中会报错:不允许使用不完整的类型

防止继承的发生:

c++11提供了一种防止继承发生的方法,即定义时在类名后跟关键字final。

当我们用一个派生类对象为一个基类对象初始化或赋值时,只有该派生类对象中的基类部分会被拷贝、移动或赋值,它的派生类部分将被忽略。

----------------------------------------------------------------------------------------------------------------

class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() {}; virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
}; class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
}; int main()
{
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest; system("pause");
}

输出结果是:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!

如果把类ClxBase析构函数前的virtual去掉,那输出结果如下:

Do something in class ClxDerived!

上述例子中会先调用基类的构造函数,再调用派生类的构造函数;而析构时,先调用派生类的析构函数,再调用基类的析构函数

一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。

基类的析构函数一般都是虚函数是为了当删除一个指向派生类对象的基类指针时,派生类的析构函数会被调用。由函数的调用流程可以得知,先确定指针的静态类型,然后在静态类型对应的类中查找该函数,当找到后,如果该函数是虚函数,那么会在运行时根据指针的动态类型来调用函数,否则编译时直接生成调用当前类中的该函数的代码。所以若析构函数不是虚函数,当删除一个指向派生类对象的基类指针时不会调用派生类的析构函数。

【c++】面向对象程序设计之关于继承的更多相关文章

  1. java面向对象三大特性之继承

    通过重用已经测试并验证通过的代码,怎样才减少开发工作,所有开发团队都在为一问题而努力.一个久经考验的方法是通过有效地使用Java继承优化应用程序开发. 继承的从某种意义上讲,继承的短暂美就如同宇宙中所 ...

  2. 周强 201771010141 《面向对象程序设计(java)》第七周学习总结

    实验目的与要求 (1)进一步理解4个成员访问权限修饰符的用途: (2)掌握Object类的常用API用法: (3)掌握ArrayList类用法与常用API: (4)掌握枚举类使用方法: (5)结合本章 ...

  3. JavaScript 面向对象程序设计(下)——继承与多态 【转】

    JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论 ...

  4. javascript之面向对象程序设计(对象和继承)

    总结的文章略长,慎点. 知识点预热 引用类型:引用类型的值(对象)是引用类型的一个实例.在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起.在其他面向对象语言中被称为类,虽然 ...

  5. Java面向对象程序设计--与C++对比说明:系列3(Java 继承机制)

    继承(inheritance)背后的核心思想是:       bonus = b;    }      } Java没有像C++那样提供多继承机制,但提供了接口机制,在后面我们将详细探究接口机制的实现 ...

  6. Python基础(16)_面向对象程序设计(类、继承、派生、组合、接口)

    一.面向过程程序设计与面向对象程序设计 面向过程的程序设计:核心是过程,过程就解决问题的步骤,基于该思想设计程序就像是在设计一条流水线,是一种机械式的思维方式 优点:复杂的问题的简单化,流程化 缺点: ...

  7. [.net 面向对象程序设计深入](2)UML——在Visual Studio 2013/2015中设计UML用例图

    [.net 面向对象程序设计深入](2)UML——在Visual Studio 2013/2015中设计UML用例图  1.用例图简介 定义:用例图主要用来描述“用户.需求.系统功能单元”之间的关系. ...

  8. [.net 面向对象程序设计深入](1)UML——在Visual Studio 2013/2015中设计UML类图

    [.net 面向对象程序设计深入](1)UML——在Visual Studio 2013/2015中设计UML类图 1.UML简介 Unified Modeling Language (UML)又称统 ...

  9. [.net 面向对象程序设计进阶] (13) 序列化(Serialization)(五) Json 序列化利器 Newtonsoft.Json 及 通用Json类

    [.net 面向对象程序设计进阶] (13) 序列化(Serialization)(五) Json 序列化利器 Newtonsoft.Json 及 通用Json类 本节导读: 关于JSON序列化,不能 ...

随机推荐

  1. (10)zabbix item key详解

    1. 灵活的参数 参数位置可用接收任意参数则是灵活的.例如vfs.fs.size[*],”*”星号可以使用任意的参数,例如:vfs.fs.size[/]vfs.fs.size[/opt] 2. Key ...

  2. tkinter学习-菜单与画布

    阅读目录 Menu 菜单控件 Menubutton 菜单按钮控件 OptionMenu 选项菜单 Canvas 画布控件 Menu: 说明:菜单控件,显示菜单栏,下拉菜单和弹出菜单 属性:创建一个顶级 ...

  3. bash初识,特性,用法/网站

    目录 一.Bash初识 Bash Shell介绍 Bash Shell的作用 Bash 两种方式 命令提示符 二.Shell的基本语法 三.Shell的基本特性 1.命令补全 tab 2. Linux ...

  4. 【MySQL】Got fatal error 1236原因和解决方法

    一 前言  MySQL 的主从复制作为一项高可用特性,用于将主库的数据同步到从库,在维护主从复制数据库集群的时候,作为专职的MySQL DBA,笔者相信大多数人都会遇到“Got fatal error ...

  5. css3小代码

    1.三角 <!doctype html> <html lang="en"> <head> <meta charset="UTF- ...

  6. SPOJ GSS6 Can you answer these queries VI ——Splay

    [题目分析] 增加了插入和删除. 直接用Splay维护就好辣! 写了一个晚上,(码力不精),最后发现更新写挂了 [代码] #include <cstdio> #include <cs ...

  7. [BZOJ1572] [Usaco2009 Open]工作安排Job(贪心 + 堆)

    传送门 把任务按照d排序 一次加入到堆中,如果当前放不进堆中,并且比堆中最小的大, 就从堆中弹出一个数,再把当前的数放进去 #include <queue> #include <cs ...

  8. 解决 sqlalchemy 报错:(1193, "Unknown system variable 'tx_isolation'")

    1出现此报错的原因是使用的mysql8.0 以前用的是:tx_isolation 现在用是: transaction_isolation a.通过升级 sqlalchemy 的方法可以解决此问题, p ...

  9. Modular Production Line

     Modular Production Line 时空限制: 1000ms /65536K   An automobile factory has a car production line. Now ...

  10. 仓库建设(bzoj 1096)

    Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天, ...