虚函数

C++多态技术

孤街浪徒 提交于 2019-12-03 15:57:23
C++多态技术 多态(polymorphism)一词最初来源于希腊语polumorphos,含义是具有多种形式或形态的情形。在程序设计领域,一个广泛认可的定义是 “一种将不同的特殊行为和单个泛化记号相关联的能力”。和纯粹的面向对象程序设计语言不同,C++中的多态有着更广泛的含义。除了常见的通过类继承和虚函 数机制生效于运行期的动态多态(dynamic polymorphism)外,模板也允许将不同的特殊行为和单个泛化记号相关联,由于这种关联处理于编译期而非运行期,因此被称为静态多态 (static polymorphism)。 事实上,带变量的宏和函数重载机制也允许将不同的特殊行为和单个泛化记号相关联。然而,习惯上我们并不将它们展现出来的行为称为多态(或静态多态)。今 天,当我们谈及多态时,如果没有明确所指,默认就是动态多态,而静态多态则是指基于模板的多态。不过,在这篇以C++各种多态技术为主题的文章中,我们首 先还是回顾一下C++社群争论已久的另一种“多态”:函数多态(function polymorphism),以及更不常提的“宏多态(macro polymorphism)”。 函数多态 也就是我们常说的函数重载(function overloading)。基于不同的参数列表,同一个函数名字可以指向不同的函数定义: // overload_poly.cpp #include

C++ 多态详解及常见面试题

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-03 13:34:23
       今天,讲一讲多态:         多态就是 不同对象对同一行为会有不同的状态 。 (举例 : 学生和成人都去买票时,学生会打折,成人不会)        实现多态有两个条件: 一是 虚函数 重写 , 重写就是用来设置不同状态的                  二是对象调用虚函数时必须是 指针或者引用                       什么是虚函数?什么是重写?         虚函数是带有 virtual 关键字的 成员函数          子类有个和父类 完全相同 (函数名,形参,返回值都相同,协变和析构函数除外) 的 虚函数 ,就称子类虚函数重写父类虚函数                  多态的原理?         多态是用 虚函数表 实现的。        有虚函数的类都会生成一个虚函数表, 这个表在 编译时 生成。        虚函数表是一个 存储虚函数地址的 数组 ,以NULL结尾。        如果要生成子类虚表,就要经过三个步骤:第一步,将父类虚表内容 拷贝 到子类虚表上;                          第二步,将子类 重写的虚函数覆盖掉 表中父类的虚函数;                          第三步,如果子类有 新增加 的虚函数,按 声明次序加到最后        多态如何调用?        

关于多态的概念以及用途的简单理解(通俗易懂)

亡梦爱人 提交于 2019-12-03 10:21:21
多态的定义和一些理解: (1)派生类对象的地址可以赋值给基类指针。对于通过基类指针调用基类和派生类中都有的同名、同参数表的虚函数的语句,编译时并不确定要执行的是基类还是派生类的虚函数;而当程序运行到该语句时,如果基类指针指向的是一个基类对象,则基类的虚函数被调用,如果基类指针指向的是一个派生类对象,则派生类的虚函数被调用。这种机制就叫作“多态(polymorphism)”。 (2)所谓“虚函数”,就是在声明时前面加了 virtual 关键字的成员函数。virtual 关键字只在类定义中的成员函数声明处使用,不能在类外部写成员函数体时使用。静态成员函数不能是虚函数。 (3)包含虚函数的类称为“多态类”。 (4)多态可以简单地理解为同一条函数调用语句能调用不同的函数;或者说,对不同对象发送同一消息,使得不同对象有各自不同的行为。 (5)多态在面向对象的程序设计语言中如此重要,以至于有类和对象的概念,但是不支持多态的语言,只能被称作“基于对象的程序设计语言”,而不能被称为“面向对象的程序设计语言”。例如,Visual Basic 就是“基于对象的程序设计语言”。 一个小例子: 执行结果: 当我们没有使用多态,父类指针只能够访问子类的成员,而不能访问成员函数,当我们在父类的成员函数前面加一个virtual,使其成为了一个虚函数过后,父类的指针就可以访问子类的成员函数了。 总得来说

C++中的out-of-line虚函数

风格不统一 提交于 2019-12-03 06:51:29
引子 在现实编码过程中,曾经遇到过这样的问题“warning:’Base’ has no out-of-line method definition; its vtable will be emitted in every translation unit”。由于对这个warning感兴趣,于是搜集了相关资料来解释这个warning相关的含义。 C++虚表内部架构 Vague Linkage out-of-line virtual method C++虚表内部架构 在C++实现机制RTTI中,我们大概谈到过C++虚表的组织结构。 但是我们对C++虚表的详细实现细节并没有具体谈及,例如在继承体系下虚表的组织以及在多重继承下虚表的组织方式。 (1)没有继承情况下的类虚表结构 #include <iostream> using namespace std; class Base { public: virtual void Add() { cout << "Base Virtual Add()!"<< "\n"; } virtual void Sub() { cout << "Base Virtual Sub()!" << "\n"; } virtual void Div() { cout << "Base Virtual Div()!" << "\n"; } }; int main()

C++ warning:’xxx‘ has no out-of-line virtual method definitions...

五迷三道 提交于 2019-12-03 06:50:34
前言 最近在复习一些 C++基础知识,写了一些 C++的代码,当我在类中定义了虚函数并且直接在类定义内部实现这些虚函数时,编译器就会报警告:’xxx‘ has no out-of-line virtual method definitions;its vtable will be emitted in every translation unit. 如下图: 如何解决 以前好像从来没留意过这些问题,然后决定找找原因,后来查了一些资料终于找到真正的原因,来看一段话: If a class is defined in a header file and has a vtable (either it has virtual methods or it derives from classes with virtual methods), it must always have at least one out-of-line virtual method in the class. Without this, the compiler will copy the vtable and RTTI into every .o file that #includes the header, bloating .o file sizes and increasing link times

虚函数表:QT5与VS2015的差异

匿名 (未验证) 提交于 2019-12-03 00:40:02
问题原自下面一段代码: 初学C++虚函数表时,以下代码在QT和VS(版本如题)编译结果不同。 1 #include <iostream> 2 using namespace std; 3 4 5 class Demo 6 { 7 public : 8 Demo() 9 { 10 cout << " Demo() " << endl; 11 } 12 virtual ~ Demo() 13 { 14 cout << " ~Demo() " << endl; 15 } 16 virtual void Fun1() 17 { 18 cout << " Fun1() " << endl; 19 } 20 virtual void Fun2() 21 { 22 cout << " Fun2() " << endl; 23 } 24 virtual void Fun3() 25 { 26 cout << " Fun3() " << endl; 27 } 28 }; 29 30 typedef void (FUN)(); 31 int main() 32 { 33 Demo D1; 34 35 int *p = ( int *)& D1; 36 37 FUN * pFun = (FUN *)*(( int *)*p + 1 ); 38 pFun(); 39 40 return 0 ; 41 }

为什么构造函数内部不能调用虚函数

匿名 (未验证) 提交于 2019-12-03 00:40:02
其实也不是不能调用, 调用自然是可以的,只不过构造函数中的虚函数不具有多态性 ,不能达到我们想要的效果。 class Base { public : Base() { Fuction(); } virtual void Fuction() { cout << " Base::Fuction " << endl; } }; class A : public Base { public : A() { Fuction(); } virtual void Fuction() { cout << " A::Fuction " << endl; } }; // 这样定义一个A的对象,会输出什么? A a; 我们一般想让它输出 A::Fuction A::Fuction 但其实实际输出为 Base::Fuction A::Fuction 给出的原因是说构造基类的时候,还未初始化派生类的成员变量。而网上很多说法说是虚表未建立。 具有虚函数的类的内存结构里除了非静态变量,还有一个虚指针,指向了虚表。 网上说的虚表未建立的说法是不合适的 ,因为同一个类的所有实例共享了同一张虚表。确切地说 ,是在基类的构造函数执行的时候,虚指针对应的内存里存放的是基类虚表的地址 。 c++ primer中明确指明,类的成员变量的初始化是完成在构造函数被调用后、构造函数函数体重的代码执行之前的。对于具有虚函数的类

c++中的 虚函数 纯虚函数 虚基类

匿名 (未验证) 提交于 2019-12-03 00:37:01
一、前言 https://blog.csdn.net/a345203172/article/details/21697687 ,为了理解下C++中虚函数 纯虚函数 虚基类的基础知识点。 二、虚函数 纯虚函数 虚基类三者区别 2.1、虚函数 1.继承 2.重载 3.父类指针指向子类对象。 看一下程序 第一个是没有使用virtual的,没有使用多态的: class A { public: void printf(){ cout<<"printf A"<<endl; } }; class B : public A { public: void printf(){ cout<<"printf B"<<endl; } }; int main(int argc, const char * argv[]) { A *a = new A(); a->printf(); B *b = new B(); b->printf(); return 0; } 结果: printf A printf B 这是最基本的用法,没有多态,只有继承,下面是使用了多态但是没有引用virtual关键字的情况,多态的作用请参考其他地方的文章: int main(int argc, const char * argv[]) { A *a = new B(); a->printf(); return 0; } 结果:

C++ 多态

匿名 (未验证) 提交于 2019-12-03 00:37:01
1.1 定义 1.2 规则 2 虚函数 2.1 定义 虚函数 是一种在基类定义为virtual的函数,并在一个或多个派生类中重新定义的函数。 2.2 格式 class 类名{ vitrual 函数声明 }; 2.3 规则 在基类中用virtual声明成员函数为虚函数。类外实现虚函数时,不必再加virtual; 在派生类中重新定义此函数称为覆写,要求函数名,返回类型,函数参数个数及类型全部匹配。并根据派生类的需要重新定义函数体; 当一个成员函数被声明为虚函数后,其派生类中完全相同的函数(显示的写出)也为虚函数。可以在其前面加上vitrual以示清晰; 定义一个基类对象的指针,并使其指向子类的对象,通过该指针调用虚函数,此时调用的就是指针变量指向对象的同名函数; 子类中覆写的函数,可以为任意访问类型,依子类需求决定; 只有类中的成员函数才能声明为虚函数,因为虚函数仅适用于与有继承关系的类对象,所以普通函数(包括友元函数)不能说明为虚函数; 静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象; 内联函数不能是虚函数,因为内联函数不能再运行中动态确定位置; 构造函数不能是虚函数,析构函数可以是虚函数,而且通常声明为虚函数; 3 纯虚函数 3.1 格式 class 类名{ vitrual 函数声明=0; }; 3.2 规则 含有纯虚函数的类,称为 抽象基类 ,不可实例化

c++中的类型识别

匿名 (未验证) 提交于 2019-12-03 00:36:02
基类指针指向子类对象 基类引用成为子类对象的别名 静态类型-变量(对象)自身的类型 动态类型-指针(引用)所指向对象的实际类型 基类指针是否可以强制类型转换为子类指针取决于动态类型! c++中如何得到动态类型? 解决方案-利用多态 1.在基类中定义虚函数返回具体的类型信息 2.所有的派生类都必须实现相关的虚函数 3.每个类中的类型虚函数都需要不同的实现 多态解决方案的缺陷 必须从基类开始提供类型虚函数 所有的派生类都必须重写类型虚函数 每个派生类的类型名必须唯一 c++提供了typeid关键字用于获取类型信息 typeid关键字返回对应参数的类型信息 typeid返回一个type_info类对象 当typeid的参数为NULL时将抛出异常 typeid关键字的使用 Int i = 0; const type_info& tiv = typeid( i ); const type_info& tii = typeid( int ); typeid的注意事项 当参数为类型时:返回静态类型信息 当参数为变量时:   不存在虚函数表-返回静态类型信息   存在虚函数表-返回动态类型信息 小结 c++中有静态类型和动态类型的概念 利用多态能够实现对象的动态类型识别 typeid是专用于类型识别的关键字 typeid能够返回对象的动态类型信息 原文:https://www.cnblogs