精华内容
下载资源
问答
  • c++多态实现的三种形式
    千次阅读
    2021-05-23 08:34:50

    多态是一种不同的对象以单独的方式作用于相同消息的能力,这个概念是从自然语言中引进的。例如,动词“关闭”应用到不同的事务上其意思是不同的。关门,关闭银行账号或关闭一个程序的窗口都是不同的行为;其实际的意义取决于该动作所作用的对象。

    大多数面向对象语言的多态特性都仅以虚拟函数的形式来实现,但C++除了一般的虚拟函数形式之外,还多了两种静态的(即编译时的)多态机制:

    1、操作符重载:例如,对整型和串对象应用 += 操作符时,每个对象都是以单独的方式各自进行解释。显然,潜在的 += 实现在每种类型中是不同的。但是从直观上看,我们可以预期结果是什么。

    2、模板:例如,当接受到相同的消息时,整型vector对象和串vector对象对消息反映是不同的,我们以关闭行为为例:

    vector < int > vi;  vector < string > names;

    string name(“VC知识库”);

    vi.push_back( 5 ); // 在 vector 尾部添加整型

    names.push_back (name); // 添加串和添加整型体现差别的潜在的操作

    静态的多态机制不会导致与虚拟函数相关的运行时开。此外,操作符重载和模板两者是通用算法最基本的东西,在STL中体现得尤为突出。

    更多相关内容
  • 静态多态和动态多态的区别其实只是在什么时候将函数实现和函数调用关联起来,是在编译时期还是运行时期,即函数地址是早绑定还是晚绑定的。静态多态是指在编译期间就可以确定函数的调用地址,并生产代码,这就是静态...
  • C++多态三种实现方式

    千次阅读 2020-10-14 19:52:01
    多态实现方式分为块:重载、重写、重定义。下面我们来谈一谈他们各自的实现方式和实现原理。 重载 实现方式 重载是在同一作用域内(不管是模块内还是类内,只要是在同一作用域内),具有相同函数名,不同的形参...

    定义
    多态的定义简单来说就是使一条语句有多种状态。

    实现方式
    多态的实现方式分为三块:重载、重写、重定义。下面我们来谈一谈他们各自的实现方式和实现原理。

    重载
    实现方式
    重载是在同一作用域内(不管是模块内还是类内,只要是在同一作用域内),具有相同函数名,不同的形参个数或者形参类型。返回值可以相同也可以不同(在函数名、形参个数、形参类型都相同而返回值类型不同的情况下无法构成重载,编译器报错。这个道理很简单,在函数调用的时候是不看返回值类型的)。

    实现原理
    重载是一种静态多态,即在编译的时候确定的。C++实现重载的方式是跟编译器有关,编译过后C++的函数名会发生改变,会带有形参个数、类型以及返回值类型的信息(虽然带有返回值类型但是返回值类型不能区分这个函数),所以编译器能够区分具有不同形参个数或者类型以及相同函数名的函数。插一句,在C语言中编译器编译过后函数名中不会带有形参个数以及类型的信息,因此C语言没有重载的特性。由此带来麻烦的一点是如果想要在C++中调用C语言的库,需要特殊的操作(extern “C”{})。库中的函数经过C编译器编译的话会生成不带有形参信息的函数名,而用C++的编译器编译过后会生成带有形参信息的函数名,因此将会找不到这个函数。extern “C”{}的作用是使在这个作用域中的语句用C编译器编译,这样就不会出错。这也是一种语言兼容性的问题。

    重写
    实现方式
    重写是在不同作用域内(一个在父类一个在子类),函数名、形参个数、形参类型、返回值类型都相同并且父类中带有virtual关键字(换言之子类中带不带virtual都没有关系)。有一种特殊的情况:函数返回值类型可以不同但是必须是指针或者引用,并且两个虚函数的返回值之间必须要构成父子类关系。这种情况称之为协变,也是一种重写。引入协变的好处是为了避免危险的类型转换。

    实现原理
    重写是一种动态多态,即在运行时确定的。C++实现重写的方式也跟编译器有关,编译器在实例化一个具有虚函数的类时会生成一个vptr指针(这就是为什么静态函数、友元函数不能声明为虚函数,因为它们不实例化也可以调用,而虚函数必须要实例化,这也是为什么构造函数不能声明为虚函数,因为你要调用虚函数必须得要有vptr指针,而构造函数此时还没有被调用,内存中还不存在vptr指针,逻辑上矛盾了)。vptr指针在类的内存空间中占最低地址的四字节。vptr指针指向的空间称为虚函数表,vptr指针指向其表头,在虚函数表里面按声明顺序存放了虚函数的函数指针,如果在子类中重写了,在子类的内存空间中也会产生一个vptr指针,同时会把父类的虚函数表copy一下当做自己的,然后如果在子类中重新声明了虚函数,会按声明顺序接在父类的虚函数函数指针下。而子类中重写的虚函数则会替换掉虚函数表中原先父类的虚函数函数指针。重点来了,在调用虚函数时,不管调用他的是父类的指针、引用还是子类的指针、引用,他都不管,只看他所指向或者引用的对象的类型(这也称为动态联编),如果是父类的对象,那就调用父类里面的vptr指针然后找到相应的虚函数,如果是子类的对象,那就调用子类里面的vptr指针然后找到相应的虚函数。当然这样子的过程相比静态多态而言,时间和空间上的开销都多了(这也是为什么内联函数为什么不能声明为虚函数,因为这和内联函数加快执行速度的初衷相矛盾)。

    重定义
    实现方式
    重定义是在不同作用域内的(一个在父类一个在子类),只要函数名相同,且不构成重写,均称之为重定义

    实现原理
    重定义的实现原理跟继承树中函数的寻找方式有关,他会从当前对象的类作用域内开始查找同名的函数,如果没有找到就一直向上查找直到基类为止。如果找到一个同名的函数就停止。这也就说明他不管函数的形参类型或者个数是不是一样,只要函数名一样,他就认为是找到了,如果这时候形参类型或者个数不一致,编译器就会报错。多重继承的查找,如果在同一层内出现一样的函数声明那么编译器会报错不知道调用哪一个函数,这类问题也叫钻石继承问题。钻石问题的解决方案可以通过虚继承来实现,这样就不会存在多个一样的函数声明。

    展开全文
  • C++多态实现方式详情

    2022-04-10 13:36:25
    更多python、PHP、JAVA、C、C++教程请到友情连接: 菜鸟教程https://www.piaodoo.com 茂名一技http://www.enechn.comppt制作教程步骤 http://www.tpyjn.cn 兴化论坛http://www.yimoge.cn 电白论坛 ...

    更多python、PHP、JAVA、C、C++教程请到友情连接: 菜鸟教程https://www.piaodoo.com

    茂名一技http://www.enechn.com

    ppt制作教程步骤 http://www.tpyjn.cn

    兴化论坛http://www.yimoge.cn

    电白论坛 http://www.fcdzs.com

    表格制作excel教程 http://www.tsgmyy.cn


    学习通 http://www.hssi.net/


    :文章转自公众号:Coder梁(ID:Coder_LT)

    在我们之前介绍的继承的情况当中,派生类调用基类的方法都是不做任何改动的调用。

    但有的时候会有一些特殊的情况,我们会希望同一个方法在不同的派生类当中的行为是不同的。举个简单的例子,比如speak方法,在不同的类当中的实现肯定是不同的。如果是Human类,就是正常的说话,如果是Dog类可能是汪汪,而Cat类则是喵喵。

    在这种情况下只是简单地使用继承是无法满足我们的要求的,最好能够有一个机制可以让方法有多种形态,不同的对象去调用的逻辑不同。这样的行为称为多态。

    这里稍微强调一下,多态是一种面向对象的设计思路,本身和C++不是强绑定的,其他语言当中一样有多态,只不过实现的方式可能有所不同。

    在C++当中有两种重要的机制用于实现多态:

    • 在派生类当中重新定义基类的方法
    • 使用虚方法

    我们来看一个例子:

    class Mammal {
    ?private:
    ? string name;
    ?public:
    ? Mammal(string n): name(n) {}
    ? ? ?string Name() const{
    ? ? ? ? ? ? return name;
    ? ? ? ? }
    ? virtual void speak() const {
    ? ?cout << "can't say anything" << endl;
    ? }
    ? ? ?virtual ~Mammal() {};
    };
    

    class Human : public Mammal{
    ?private:
    ? string job;
    ?public:
    ? Human(string n, string j): Mammal(n), job(j) {}
    ? virtual void speak() const {
    ? ?cout << “i’m human” << endl;
    ? }
    };

    由于示例比较简单,所以我们把类的声明和实现写在一起了。

    从结构上来看,这就是一个简单的继承,我们实现了两个类,一个叫做Mammal,一个叫做Human,然后给它们各自定义了一些成员变量。

    值得注意的是speak函数,我们在函数声明前面加上了一个关键字virtual,这表示这是一个虚函数。

    方法被定义成虚方法之后,在程序执行的时候,将会根据派生类的类型来选择执行的方法版本。在进行调用的时候,程序是根据对象类型而不是引用和指针的类型来选择执行的方法,

    如:

    Mammal *m = new Human("man", "spiderman");
    m->speak();

    这里我们用一个Mammal的指针指向了一个Human类型的对象,当我们调用方法的时候,由于speak方法是一个虚方法。因此执行的时候程序会根据对象的类型也就是Human去执行Human对象中的speak方法,而不是Mammal中的。

    通常我们会将析构函数也设置成虚方法,因为派生类当中往往有一些专属成员,这是一种惯例。因为如果析构函数不是虚函数,那么只会调用对应指针类型的析构函数,这意味着可能在一些情况下产生错误和问题。

    在上述的示例当中,我们是将类方法的实现和声明写在一起了,如果还是采取和之前一样分开实现的方式,需要注意我们无需在函数签名中加上virtual关键字。

    到此这篇关于C++多态实现方式详情的文章就介绍到这了,更多相关C++多态内容请搜索菜鸟教程www.piaodoo.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持菜鸟教程www.piaodoo.com!

    展开全文
  • c++多态及其实现

    2021-05-01 21:44:40
    c++是一门面向对象的语言,具有继承、封装和多态三大特性,本文我们总结一下c++多态的特性及其实现方法。多态指的是调用同一接口,表现出不同的特性,分为静态多态和动态多态。静态多态指在编译期就能确定其特性的...

    c++是一门面向对象的语言,具有继承、封装和多态三大特性,本文我们总结一下c++中多态的特性及其实现方法。多态指的是调用同一接口,表现出不同的特性,分为静态多态和动态多态。静态多态指在编译期就能确定其特性的多态,而动态多态需要在运行时确定其特性。

    静态多态

    静态多态包括重载和模板两种方式。c++重载是指函数在调用时,即使调用的函数名相同,也可以根据参数列表来确定其调用对象,比如下面的代码中有四个函数,main()函数中的调用,根据参数列表的不同,可以找到对应的函数入口。

    //函数1
    void foo(){} 
    //函数2
    void foo(int x){}
    //函数3
    void foo(int x, float y){};
    //函数4
    void foo(float x, int y){};
    
    
    int main(){
        foo();  //调用函数1
        foo(3); //调用函数2
        foo(3, 5.7); //调用函数3
        foo(3.8, 5); //调用函数4
    }
    

    需要说明的是,重载仅能识别参数列表不同的情况,这里也包括列表中参数类型的顺序不同,但不包括返回值的不同,比如下面的两个函数,编译器无法确定应该调用哪个函数,会出现如下图的报错。

    void foo(float x, int y){};
    int foo(float x, int y){return 0;};
    

    在这里插入图片描述

    c++支持重载是因为c++程序在编译后,这些原本同名的函数被编译成了不同名的函数,而相应的调用也修改为了新的函数名,因此重载在编译期就确定了其特性。
    c++的模板元编程也是静态多态的一种,这在stl中有着大量应用,通过传入模板元来实现相同函数的不同处理。

    动态多态

    c++的动态多态主要通过虚函数和虚表来实现。所有包含需函数的类,在类的头部都有一个虚函数表指针,这个指针指向一个虚函数表,虚函数表中存储的是虚函数指针,通过虚函数指针,程序就可以调用相应的函数,如下图描述了下面代码的内存布局。

    #include <iostream>
    using namespace std;
     
    class Base
    {
    	virtual void foo(){cout<<"Base::foo"<<endl;}
    };
     
    typedef void(*Fun)(void);
     
    int main()
    {	
    	Base d;
    
        cout << "虚函数表指针地址:" << (long long*)(&d) << endl;
        cout << "虚函数指针地址:" << (long long*)*(long long*)(&d) << endl;
     
    	Fun pFun = (Fun)*((long long*)*(long long*)(&d)); 
    	pFun();
    
        return 0;
    }
    
    

    虚函数内存布局
    上面的代码用于验证图中虚函数的内存布局,下面是代码运行的输出结果。
    在这里插入图片描述

    可以看到通过两次指针的消耗,应用程序成功调用了foo()函数,那么虚函数又是怎样实现多态的呢?

    #include <iostream>
    using namespace std;
     
    class base
    {
    public:
    	virtual void foo(){cout<<"Base::foo"<<endl;}
    };
     
    class derive:public base{
    public:
        void foo(){cout<<"derive::foo"<<endl;}
    };
    
    int main()
    {	
        base* p = new derive();
        p->foo();
        return 0;
    }
    

    上面代码的输出结果是"derive::foo",这是因为如果虚函数是子类继承自父类的虚函数,那么会对应覆盖虚表中的虚函数指针,如果是子类的虚函数,则在虚表中新增一个虚函数指针。因此在子类中重写foo成员方法会将虚表中父类的foo方法覆盖,这时即使我们通过base类实例调用,虚表中的函数也已经被重写。需要说明的是,虽然虚函数需要在运行时才确定调用的函数,虚表却早在编译阶段就已经生成。
    在多继承,菱形继承等复杂情况下,内存模型还会有更复杂的变化,我们将在后续文章中继续讨论。

    展开全文
  • C++多态实现

    2022-05-17 22:47:09
    本篇文章主要介绍了C++虚函数、动态析构、纯虚函数与抽象类的实现
  • C++ 多态 以及实现多态三种方式

    千次阅读 2014-09-02 21:59:06
    3. C++实现多态的方式... 1 4. 细说用函数重载实现多态... 2 5. 细说用模板函数实现多态... 3 6. 小结... 4 7. 细说用虚函数实现多态... 4 7.1. 虚函数是怎么回事...
  • C++ 多态的两种形式

    千次阅读 2018-09-19 17:02:26
    编译时多态是静态多态,在编译时就可以确定接口使用的形式。运行时多态是动态多态,具体引用的接口在运行时才能确定。 静态多态和动态多态的区别其实只是在什么时候将函数实现和函数调用关联起来,是...
  • C++多态有哪几方式?

    千次阅读 2019-01-08 16:53:20
    (2)动态多态(覆盖,虚函数实现) 在运行的时候,才确定调用的是哪个函数,动态绑定。运行基类指针指向派生类的对象,并调用派生类的函数。 虚函数实现原理:虚函数表和虚函数指针。 纯虚函数: virtual int fun()...
  • C++多态实现方式总结

    万次阅读 2015-11-30 14:45:52
    实现多态有两方法: 1、覆盖 *********** 覆盖是指子类重新定义父类的虚函数的做法。 2、重载 *********** 重载是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许...
  • C++多态的几种形式

    千次阅读 2013-11-19 14:30:30
    给出“多态”的定义:一个函数调用在不同的上下文环境(context,可以编译上下文也可以使 运行上下文)中被绑定到...按照这个定义,“虚拟函数,重载,模板”这个很容易归为多态的行列,但是“转型”就有一些勉强了。
  • C++如何实现多态

    2018-01-08 15:28:00
    1.什么是多态多态C++中的一个重要的基础,面向对象编程语言中,接口的多种不同的实现方式即为多态。2.多态带来的好处多态带来两个明显的好处:一是不用记大量的函数名了,二是它会依据调用时的上下文来确定实现。...
  • C++多态的理解

    千次阅读 2022-03-15 17:11:05
    多态的字面意思就是多种状态,在面向对象的程序设计中,一个接口,多种实现即为多态c++的多态性具体体现在编译和运行两个阶段。编译时多态是静态多态,在编译时就可以确定使用的接口。运行时多态是动态多态,具体...
  • C++ 多态实现

    2019-02-14 12:35:00
    C++多态,大概可分为函数重载和虚函数两类。 先说说函数重载,比较简单,就是函数参数的类型和个数不同罢了,返回值的类型不做讨论,不符合重载的定义。 函数重载是建立在name mangling上的,就是说在编译的...
  • C++ 中的多态实现和使用方法

    千次阅读 2020-05-06 22:46:27
    都说 C++ 是面向对象的语言,其中的面向对象主要包括部分:继承,封装,多态。继承和封装我们之前就简单介绍过,这里主要对多态的使用方法做一个简单说明。 赋值兼容 赋值兼容说的是在使用基类对象的地方可以...
  • } // 第二定义形式 typedef int(*Q)(int a, int b); // 函数指针类型 void fun1(int x, int y, Q p) { printf("fun1111111\n"); int a = p(x, y); // 回调函数 add(1, 2) minus(10, 5); printf("a = %d\n", a)...
  • 多态是面向对象的最主要的特性之一,是一方法的动态绑定,实现运行时的类型决定对象的行为。多态的表现形式是父类指针或引用指向子类对象,在这个指针上调用的方法使用子类的实现版本。多态是IOC、模板模式实现的...
  • C++多态的两种形式

    2019-07-12 17:30:19
    https://blog.csdn.net/k346k346/article/details/82774937
  • C++中的四种多态

    2021-02-26 00:27:36
    本文转载自The Four Polymorphisms in C++
  • 谈谈C++多态的基本使用和总结

    千次阅读 2022-04-07 15:22:12
    C++中,传入不同的对象意思:给父类传入不同的子类; 去做同一样的事意思是:父类指针或者引用调用了同一样的虚函数; 产生不同的结果意思是:调用同样的虚函数,但是结果却不一样; 构成多态的条件 继承中要构成...
  • 同一个事物多种表现形式,强调接口的重用性。看下面: class A { public: int n; virtual void show() { cout << "A show!" << endl; } virtual void show2() { cout << "A2 show!" <&...
  • 多态和封装继承作为c++面向对象的个基本特征.封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用! 2.实现...
  • 意图允许那些没有继承关系或/和没有虚函数的类能够被多态地对待。这些没有关系的类能够被使用它们的软件以一共同的行为处理。动机使用来自不同源的C++类是非常困难的。一个应用经常希望这些类能够"投射(project)...
  • 多态性(polymorphism)一词意味着具有多种形式。简而言之,我们可以将多态定义为消息以多种形式显示的能力。...在C++中,多态性主要分为两类型:编译时多态运行时多态1. 编译时多态:这种类型的多态是通过函数重...
  • C++ 多态和虚函数

    千次阅读 多人点赞 2020-05-09 12:53:37
    虚函数实现多态 #include <iostream> using namespace std; //基类People class People{ public: virtual void display(); //声明为虚函数 }; void People::display(){ cout<<"无业游民。"<<...
  • C++多态和抽象类

    2021-07-27 21:40:10
    C++多态和抽象类1. 多态1.1 虚函数概述 Reference: 明日科技 《零基础学 C++》 1. 多态 多态性(polumorphism) 是面向对象程序设计的一个重要特征,利用多态性可以设计和实现一个易于扩展的系统。在 C++ 语言中,多...
  • C++多态多态底层原理讲解

    千次阅读 2022-03-28 17:26:59
    分享学习C++多态的笔记,并将多态底层原理进行分析
  • 实现多态个条件: 1.存在继承关系 2.多态的第一,父类的引用指向子类对象 或者 多态的第二,父类的指针指向子类对象。 3.子类必须要重写父类的同名方法 程序猿神奇的手,每时每刻,这双手都在改变着...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,098
精华内容 16,839
关键字:

c++多态实现的三种形式