派生类

虚函数表

不想你离开。 提交于 2020-02-29 20:55:01
以上述类型为例: void a_fun_1();为基类虚函数,在派生类b中没有重新进行定义; void a_fun_2();为基类虚函数,在派生类b中被重新进行定义;    void b_fun_1();为派生类中新增加的虚函数; 那么基类a和派生类b的虚函数表是这样的: 规则是: 在派生类中,如果没有重新定义基类中的虚函数,将直接从原来虚函数表中继承将信息过来; 在派生类中,如果重新定了基类中的虚函数,那么将用新的虚函数地址覆盖原来的虚函数在虚函数表中的信息; 在派生类中,如果重新增加类虚函数,那么将在虚函数表中插入新的虚函数地址信息; 来源: https://www.cnblogs.com/achao123456/p/9609107.html

14--swift之派生类构造方法

拟墨画扇 提交于 2020-02-29 02:33:24
1. 指定构造和便利构造方法解析 这些是类类型的概念,在值类型里没有 class Ab { var a: Int var b: Int // 以 init 开头就是指定构造 init(a: Int,b: Int){ self.a = a self.b = b// 注意:类的指定构造方法里不能像值类型那样调用其他构造器 print("Class ab init") } // 类似值类型的构造方法,加上关键字 convenience ,搭配 self.init 就是便利构造方法,他通过调用其他的构造方法来实现初始化,当然既可以通过指定构造方法也可以是其他便利构造方法 convenience init(a: Int){ // self.a = a // b = 0 self.init(a: a,b: 0) } } 2. 派生类的构造方法 class Ab { var a: Int var b: Int // 以 init 开头就是指定构造 init(a: Int,b: Int){ self.a = a self.b = b// 注意:类的指定构造方法里不能像值类型那样调用其他构造器 print("Class ab init") } // 类似值类型的构造方法,加上关键字 convenience ,搭配 self.init 就是便利构造方法,他通过调用其他的构造方法来实现初始化

C++ Primer 第十五章 面向对象程序设计 15.2 定义基类和派生类 练习和总结

a 夏天 提交于 2020-02-28 22:43:38
基类和派生类是相对的概念,如果类A继承自类B,则类B相对于类A是基类,类A相对于类B是派生类。 15.2 定义基类和派生类 在定义基类时,我们需要将析构函数和需要子类重写的函数定义为 虚函数 , 因为当我们使用指针或者引用调用虚函数时,会根据实际绑定的动态类型来调用基类或者子类的函数。 为什么要这样做? 在定义派生类的时候解释。 之前在修饰类的成员时,我们只使用了private和public,这里还有一个protected用来修饰成员,表示派生类可以直接访问,但是其他用户(类,函数)不能对修饰为protected的成员访问。 15.2.1 定义基类 练习 15.1 使用virtual关键字修饰的函数时虚函数 15.2 用protected修饰的成员,使用类的用户不能直接访问,但是继承该类的派生类可以访问。 使用private修饰的成员,使用这个类的用户不能直接访问,继承该类的派生类也不可以直接访问。 15.3 class Quote { public : Quote ( ) = default ; virtual ~ Quote ( ) = default ; Quote ( const string & s , double p ) : bookNo ( s ) , price ( p ) { } ; virtual double net_price ( std :: size

构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数

亡梦爱人 提交于 2020-02-27 03:24:15
一、构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3. 构造函数不须要是虚函数,也不同意是虚函数,由于创建一个对象时我们总是要明白指定对象的类型,虽然我们可能通过实验室的基类的指针或引用去訪问它但析构却不一定,我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。 4. 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实际含义上看,在调用构造函数时还不能确定对象的真实类型(由于子类会调父类的构造函数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次

c++进阶八(派生类的析构函数)

心不动则不痛 提交于 2020-02-27 02:34:55
1,派生类对象被删除时析构函数的执行顺序 当对象被删除时,派生类的析构函数被执行, 先执行派生类的析构函数,再类的对象成员的析构函数,最后执行基类的析构函数 与构造函数的执行顺序相反 具体执行顺序: 1,先执行派生类的析构函数 2,执行类初始化表上的对象成员的析构函数 3,执行基类的析构函数 2,实例 通过运行下面实例来理解上面的过程 # include <iostream> using namespace std ; //类A的定义 class A { private : int x ; public : A ( int xp = 0 ) { x = xp ; cout << "A的构造函数被执行" << endl ; } ~ A ( ) { cout << "A类析构函数被执行" << endl ; } } ; class B { public : B ( ) { cout << "B的构造函数被执行" << endl ; } ~ B ( ) { cout << "B类析构函数被执行" << endl ; } } ; //创建C派生类 继承 A class C : public A { private : int y ; B b ; public : C ( int xp , int yp ) : A ( xp ) , b ( ) { y = yp ; cout <<

C++笔记(3):一些C++的基础知识点

99封情书 提交于 2020-02-26 23:05:08
前言: 找工作需要,最近看了下一些C++的基本概念,为范磊的 《零起点学通C++》,以下是一些笔记。 内容:   delete p;只是删除指针p指向内存区,并不是删除指针p,所以p还是可以用的。删除空指针所指向内存是可以的。   堆中的变量和对象时匿名的,没有名称,只能通过指针来访问。   在堆中创建对象时,在分配内存的同时会调用类的构造函数,在删除堆中对象时,会调用类的析构函数。   为了避免内存泄露,在删除一个指针后应该将其其值赋为0。   常量指针是指针指向的内存区域地址不能改变,但是该内存地址里保存的值是可以改变的,比如int a; int * const p = &a;   指向常量的指针表示指针指向的对象是不能被修改的,但是该指针可以被修改,即该指针可以指向另一块目标内存地址。比如const int a = 0; const int *p = &a; 如果A是一个类,也可以为const A* p = new A;   而指向常量的常指针表示指针本身不能被修改,其指向的内存地址内容也不能被修改。比如const int a = 0; const int * const p = &a;   引用就是别名常量。   堆中的地址是用指针来操作的,用不到别名。   如果在main函数前面的其它函数的声明和定义是一起的,则表明这个函数是内联函数!因此当该函数较长时

Java继承和多态

血红的双手。 提交于 2020-02-26 12:06:02
一、继承 1.定义: 当我们定义很多部分具有相同的属性和行为的类时,为了允许使用现有类的功能,并在无需改写原来的类的情况下,引入 继承 的概念。 我们把允许重用现有类称为基类(父类),由基类派生出来的类称为派生类(子类)。 2.基本语法: ```java class 类名 extends 父类名{ } java类的继承通过关键字extends完成,子类继承父类所有的属性和行为。 如果没有指定的父类,那么java编译器默认该类的父类为Object。 代码示例: class Animal { protected String name ; protected int age ; protected String sex ; public Animal ( String name ) { this . name = name ; } public void eat ( ) { System . out . println ( name + " eat" ) ; } } class Cat extends Animal { public Cat ( String name ) { //编译器默认调用的是父类的默认构造函数,super()可以省略 super ( name ) ; //如果父类只有一个带参数的构造函数,这里不能省略 this . name = name ; } public

C++ Primer Plus第6版18个重点笔记

╄→尐↘猪︶ㄣ 提交于 2020-02-21 06:32:43
下面是我看《C++ Primer Plus》第6版这本书后所做的笔记,作为备忘录便于以后复习。 笔记部分 C++的const比C语言#define更好的原因? 首先,它能够明确指定类型,有类型检查功能。 其次,可以使用C++的作用域规则将定义限制在特定的函数或文件中。 第三,可以将const用于更复杂的类型,比如数组和结构。 C语言中也有const,其与C++中const的区别是: 一是作用域规则不同;另一个是,在C++中可以用const值来声明数组长度。 不能简单地将整数赋给指针,如下所示: int *ptr; ptr = 0xB8000000; // type mismatch 在这里,左边是指向int的指针,因此可以把它赋给地址,但右边是一个整数。您可能知道,0xB8000000是老式计算机系统中视频内存的组合段偏移地址,但这条语句并没有告诉程序,这个数字就是一个地址。在C99标准发布之前,C语言允许这样赋值。但C++在类型一致方面的要求更严格,编译器将显示一条错误消息,通告类型不匹配。要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型: int *ptr; ptr = (int *) 0xB8000000; // type now match 这样,赋值语句的两边都是整数的地址,因此这样赋值有效。 注意

C++ Primer Plus 笔记第十三章

时光怂恿深爱的人放手 提交于 2020-02-21 05:47:21
类继承 本章内容:    is-a 关系的继承;    如何以公有方式从一个类派生出另一个类;    保护访问;    构造函数成员初始化列表;    向上和向下强制转换;    虚成员函数;    早期(静态)联编与晚期(动态)联编;    抽象基类;    纯虚函数;    何时及如何使用公有继承    面向对象编程的主要目的之一是提供可重用的代码;    C++类提供了更高层次的重用性,类库由类声明和实现构成,因为类组合了数据表示和类方法;    C++提供了比修改代码更好的方法来扩展和修改类——类继承; 13.1 一个简单的基类    从一个类派生出另一个类,原始类成为基类,继承类称为派生类;    程序清单13.1 tabtenn0.h  1 #ifndef TABTENN0_H_ 2 #define TABTENN0_H_ 3 4 class TableTennisPlayer 5 { 6 private: 7 enum {LIM = 20}; 8 char firstname[LIM]; 9 char lastname[LIM]; 10 bool hasTable; 11 public: 12 TableTennisPlayer(const char * fn = "none", const char * ln = "none", bool ht = false);

c++复习 多态

偶尔善良 提交于 2020-02-19 00:55:27
虚函数 什么是虚函数? 指向基类的指针在操作它的多态类对象时,会根据不同的类对象调用其相应的函数,这个函数就是虚函数,用virtaul修饰函数名。 虚函数的作用是在程序运行阶段动态地选择合适的成员函数 在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型,(参数顺序也要一致),以实现统一接口, 如果派生类中没有重新定义虚函数,则它集成基类的虚函数 虚函数的重写 虚函数的重写:派生类中有一个跟基类的完全相同虚函数,我们就称子类的虚函数重写了基类的虚函数,完全相同是指:函数名、参数、返回值都相同。另外虚函数的重写也叫作虚函数的覆盖。 class Person { public : virtual void BuyTicket ( ) { cout << "买票-全价" << endl ; } } ; class Student : public Person { public : virtual void BuyTicket ( ) { cout << "买票-半价" << endl ; } } ; void Func ( Person & p ) { p . BuyTicket ( ) ; } int main ( ) { Person ps ; Student st ; Func ( ps ) ; Func ( st ) ; return 0 ; } 不规范的重写行为