精华内容
下载资源
问答
  • C++ 多态实现原理
    2021-05-23 05:51:18

    一、在编译期间实现多态

    多态是指在不同的条件下表现出不同的状态,C++中通过重载函数的方法可以在编译期间实现多态。

    在编译时编译器会根据参数列表的不同寻找合适的函数。

    int Add(int left, int right)

    {

    return left + right;

    }

    double Add(double left, int right)

    {

    return left + right;

    }

    int main()

    {

    Add(10, 20);

    Add(10.0,20); //正常代码

    return 0;

    }

    二、使用虚函数实现多态

    C++中运行时多态可以通过声明一个虚函数来实现。虚函数分为纯虚方法和半虚方法,纯函数父类没有实现版本,完全交给子类,且必须实现。半虚函数父类可以实现,子类需要重写,他们都由关键字virtual修饰。

    运行时多态的条件:

    ● 必须是集成关系

    ●基类中必须包含虚函数,并且派生类中一定要对基类中的虚函数进行重写。

    ●通过基类对象的指针或者引用调用虚函数。

    重写虚函数时一定要保证函数的返回值,参数列表,函数名称完全一致

    // 半虚函数 父类实现,但希望子类重写

    virtual void withDraw(){

    a=10;

    };

    // 纯虚函数

    virtual void onDraw()=0;

    virtual ~Clazz();

    使用虚函数实现多态示例

    #ifndef student_hpp

    #define student_hpp

    #include

    #include

    using namespace std;

    class Student{

    private:

    int mAge;

    string mName;

    protected:

    int mClazz;

    public:

    Student() {};

    void setName(const string &age);

    string getName() const;

    void setAage(int &age);

    int getAge() const;

    virtual void setClassMate(int num){

    mClazz=num;

    std::cout<

    };

    virtual int getClassMate(){

    return mClazz;

    };

    virtual ~Student() {}

    };

    class Guo:public Student{

    public:

    Guo() {};

    virtual void setClassMate(int num){

    mClazz = num;

    std::cout<

    };

    virtual int getClassMate(){

    return mClazz;

    };

    virtual ~Guo();

    };

    void setClass(Student &st,int clazz){

    st.setClassMate(clazz);

    }

    int main(){

    Student student;

    Guo guo;

    setCLass(student);

    setClass(guo)

    }

    以下函数不能作为虚函数

    1)友元函数,它不是类的成员函数

    2)全局函数

    3)静态成员函数,它没有this指针

    3)构造函数,拷贝构造函数,以及赋值运算符重载(可以但是一般不建议作为虚函数)

    三、虚函数的实现原理

    一个类中如果有虚函数声明,那么这些函数会由一个虚函数表来维护

    1) 每个父类都有自己的虚表。

    2) 子类的成员函数被放到了第一个父类的表中。

    3) 内存布局中,其父类布局依次按声明顺序排列。

    4) 每个父类的虚表中的函数都被overwrite成了子类函数。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。

    更多相关内容
  • 通过C语言实现C++多态 一.C++多态的原理 在C++中,多态机制是通过虚表以及虚表指针来实现的。 我们都知道,当要实现多态功能的时候,都会通过virtual关键字来讲基类中的函数变为虚函数,然后通过子类继承后重写就...

    最近要开始准备实习了,所以需要对之前学过的知识做一些总结和回顾,最近发的博客可能更多的是对一些概念的理解。

    通过C语言实现C++多态

    一.C++多态的原理

    在C++中,多态机制是通过虚表以及虚表指针来实现的。

    我们都知道,当要实现多态功能的时候,都会通过virtual关键字来讲基类中的函数变为虚函数,然后通过子类继承后重写就能够达到多态的效果。但是实际上,在其中,编译器也为我们做了很多的工作。

    1.当编译器发现基类中存在虚函数的时候,他会自动的生成一份虚表,在虚表中,存放的就是我们这些虚函数的入口地址。

    2.当我们实例化一个带有虚函数对象的时候,编译器会给我们这个对象的前四个字节加一个虚表指针,指向我们上一步中生成的虚表,这也就是为什么当我们对一个存在虚函数的对象sizeof的时候,它的大小会比它的类成员变量总和大四个字节的原因。

    3.当我们实例化一个派生类的时候,肯定是会先调用构造函数,这里还需要插入一些知识,我们都知道,当我们定义某个基类的时候,通常的做法是将这个基类的析构函数变为virtual的,也就是虚析构函数,因为在一般的情况下,我们会使用一个基类指针来接收子类对象,当我们释放这个基类指针的时候,就会自动调用我们子类的析构函数,但是假如不定义为虚析构函数的话,就可能导致只调用基类析构函数,从而导致子类析构不完全引发内存泄漏,原因之后会讲。现在回归正题,那我们一定会有疑惑为什么不将子类构造函数设置为虚函数呢?因为从我们上述的第二步我们可以看到,当我们实例化一个对象的时候之后,我们才会有一个虚表指针来指向我们生成的虚表,那么如果我们讲构造函数定义为虚函数的话,编译器要通过虚表指针来访问虚表,但是此时连虚表、虚表指针都没有,因此就会导致报错。现在回归正题,当我们实例化一个派生类的时候,首先会调用的就是基类的构造函数,当基类构造完全后,我们会有一个虚表以及一个基类的虚表指针,指向基类的虚表;进一步我们会调用子类的构造函数,构造完成之后就会有一个虚表指针来指向子类的虚表。

    4.这样当我们使用基类指针来接收子类对象的时候,虚表指针就会指向子类的虚表,当我们调用对应的虚函数的时候,就会去虚表中查找从而调用,这样子就完成了多态。

    具体多态就不演示了。

    二.C语言实现多态

    首先我们要明确,我们实现的多态是在运行时,通过父类指针来调用子类中的虚函数。因此首先我们先定义一个函数指针,来代表我们之前所描述的虚函数。

    typedef void(*Fun) ();
    

    在定义时,为了描述所谓的继承关系,我们先通过含有has-A的方式来使得C中的结构体能有一种逻辑上的继承关系,在如下所描述的代码中,我们的基类中含有一个函数指针,同样的我们的子类中含有一个父类对象,也就是说我们的子类中也有一个函数指针。

    struct Father {
    	Fun fun;	
    };
    
    struct Son {
    	struct Father f;
    };
    

    接下来我们来实现所谓的重写,也就是通过函数指针来定义不同的行为:

    void funF() {
    	printf("this is father fun\n");
    }
    
    void funS() {
    	printf("this is son fun\n");
    }
    

    然后我们开始我们的常规操作,也就是说,通过父类指针来接收子类对象,当调用父类指针的虚函数的时候,也就是我们如上所描述的函数指针的时候,会产生多态的效果。

    void Test1() {
    	struct Father f;
    	struct Son s;
    	//对应的重写
    	f.fun = funF;
    	s.f.fun = funS;
    	
    	struct Father* p1 = &f;
    	//父类指针接收子类对象 
    	struct Father* p2 = (struct Father*)&s;
    	p1->fun();
    	p2->fun();
    }
    

    最终结果如下所示:
    在这里插入图片描述

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

    2021-11-15 22:12:42
    C语言实现C++多态 C++中多态实现是基于虚函数表实现的,每个具备多态性对象的内部都会有一个隐藏的虚函数表,虚函数表里面的函数指针指向具体的函数实现,可能是父类中的实现,或是子类重写了的方法。C语言没有天然...

    C++中多态实现是基于虚函数表实现的,每个具备多态性对象的内部都会有一个隐藏的虚函数表,虚函数表里面的函数指针指向具体的函数实现,可能是父类中的实现,或是子类重写了的方法。C语言没有天然的多态支持,但是按照C++的实现原理,也能写出多态特性的代码。
    下面代码就是用C实现多态。结构体Animal中有两个函数指针,eat和drink。Cat结构体通过组合的方式包含Animal对象,此时,Cat结构体也间接获得了eat和drink方法,通过Cat结构体实现原本Animal里面的方法。创建一个Cat结构体指针,将该Cat结构体指针强转成Animal类型的指针,就可以直接调用Animal对象中的方法。

    #include <stdio.h>
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    typedef struct Animal{
        void (*eat)(void* this);
        void (*drink)(void* this);
    }Animal;
    
    typedef struct Cat{
        Animal base;
        char name[16];
        void (*say)(void* this);
    }Cat;
    
    void Say(void* this){
        assert(this);
        Cat* cat = (Cat*)this;
        printf("I am %s\n", cat->name);
    }
    
    void CatEat(void* this){
        assert(this);
        Cat* cat = (Cat*)this;
        cat->say(cat);
        
        printf("I am eating.\n");
    }
    
    void CatDrink(void* this){
        assert(this);
        Cat* cat = (Cat*)this;
        cat->say(cat);
    
        printf("I am drinking.\n");
    }
    
    Cat* CatConstruct(){
        Cat* cat = calloc(1, sizeof(Cat));
        strcpy(cat->name, "cat");
        cat->say = Say;
        cat->base.drink = CatDrink;
        cat->base.eat = CatEat;
        return cat;
    }
    
    int main(){
        Animal* animal = (Animal*)CatConstruct();
    
        animal->eat(animal);
        animal->drink(animal);
        free(animal);
        return 0;
    }
    
    展开全文
  • 文章目录一、C语言实现继承二、C语言实现多态(1)静态多态(2)动态多态 一、C语言实现继承 原理:结构体组合类 //基类 typedef struct Base { //基类自身属性和方法 int b_val = 0; void show() { printf("b...

    一、C语言实现继承

    原理:结构体组合类

    //基类
    typedef struct Base
    {
    	//基类自身属性和方法
    	int b_val = 0;
    	void show()
    	{
    		printf("b_val:%d\n", b_val);
    	}
    }Base;
    typedef struct Son
    {
    	//隐藏基类对象
    	Base base;
    	//派生类自身属性和函数
    	int s_val = 10;
    	void show()
    	{
    		printf("s_val:%d\n", s_val);
    	}
    
    }Son;
    
    int main()
    {
    	Son s;
    	s.show();
    	s.base.show();
    	return 0;
    }
    

    在这里插入图片描述


    二、C语言实现多态

    (1)静态多态

    原理:使用宏实现
    静态多态:函数重载、运算符重载

    #define SUM(A,B) (A)+(B)
    int main()
    {
    	printf("%d\n", SUM(10, 20));
    	string s1("hello");
    	string s2("world");
    	cout << SUM(s1, s2) << endl;
    	return 0;
    }
    

    在这里插入图片描述

    (2)动态多态

    注意:当公有继承的基类中不存在虚函数时,构建的对象内存中不含有__vfptr指针
    原理:继承前提下,使用函数指针、虚表指针、理解构建虚函数表的过程

    在实现动态多态前,我们先看看C++提供给我们的类结构是怎样的,以下面代码为例

    class Base
    {
    private:
    	int b_val;
    public:
    	Base(int x = 0): b_val(x){}
    	virtual void fun()
    	{
    		cout << "b_val:"<< b_val << endl;
    	}
    };
    
    class Son : public Base
    {
    private:
    	int s_val;
    public:
    	Son(int x = 0) : Base(x), s_val(x + 10) {}
    	virtual void fun()
    	{
    		cout << "s_val:" << s_val << endl;
    	}
    };
    int main()
    {
    	Son s;
    	return 0;
    }
    

    s对象内存结构:
    在这里插入图片描述
    实现代码:

    #include<iostream>
    using namespace std;
    //虚函数表结构
    typedef struct vftable
    {
    	void (*show)(void*);	//根据所需自定义虚函数指针类型
    }vftable;
    
    //基类
    typedef struct Base
    {
    	//虚表指针
    	vftable* __vfptr;
    	//基类自身属性
    	int b_val = 0;
    }Base;
    
    
    typedef struct Son
    {
    	//隐藏基类对象
    	Base base;
    
    	//派生类自身属性和函数
    	int s_val = 10;
    }Son;
    
    //基类函数
    void ShowBase(void* th)
    {
    	Base* bs = (Base*)th;
    	printf("b_val:%d\n", bs->b_val);
    }
    //派生类函数
    void ShowSon(void* th)
    {
    	Son* ss = (Son*)th;
    	printf("s_val:%d\n", ss->s_val);
    }
    
    //生成基类虚函数表
    vftable base_vftable = { ShowBase};
    //生成派生类虚函数表
    vftable son_vftable = { ShowSon };
    
    //基类构造函数
    Base* create_Base(int val)
    {
    	Base* tmp = (Base*)malloc(sizeof(Base));
    	memset(tmp, 0, sizeof(Base));
    	//设置虚表指针 指向基类虚函数表
    	tmp->__vfptr = &base_vftable;
    	//初始化Base中成员
    	tmp->b_val = val;
    	return tmp;
    }
    //派生类构造函数
    Son* create_Son(int val)
    {
    	Son* tmp = (Son*)malloc(sizeof(Son));
    	memset(tmp, 0, sizeof(Son));
    	//设置虚表指针
    	tmp->base.__vfptr = &son_vftable;
    	
    	//初始化Base中成员
    	tmp->base.b_val = 0;
    	//初始化Son中成员
    	tmp->s_val = val;
    	
    	return tmp;
    }
    
    int main()
    {
    	//1.构造派生类对象
    	Son* sp = create_Son(10);
    
    	Base* bp = (Base*)sp;
    	//2.调用show函数指针 查派生类 虚函数表调用派生类的函数
    	bp->__vfptr->show((void*)sp);
    	free(sp);
    	bp = NULL;
    	sp = NULL;
    	
    	return 0;
    }
    

    结果:使用基类指针成功调用派生类成员方法

    在这里插入图片描述
    对应内存结构:

    在这里插入图片描述


    参考文章:
    C语言实现多态

    展开全文
  • C语言实现多态

    2021-05-20 19:16:11
    C语言实现多态首先声明,大神就不要看了。小弟水平有限。C++多态是通过虚函数表实现的,类似于JAVA多态的实现方式。关于Java多态的实现方式可以看我之前写过的一篇不是很完善的文章。从JVM角度看Java多态。Java和C++...
  • C语言多态

    千次阅读 2021-11-25 23:01:05
    一般实现多态需满足:必须要有继承,必须要有重写 ,必须要父类引用/指针指向子类对象,三个必要条件。本文将从多态的三个必要条件入手,借鉴Javascript原型链设计并实现了一种C语言的多态实现范式。
  • c语言实现多态

    2019-02-23 17:29:15
    c语言实现多态原理
  • C语言实现面向对象的封装、继承、多态。 实践实验 代码实现: //未新建.h文件,仅使用了.c #include "stdint.h" #include "stdio.h" #include "string.h" #include "stdlib.h #define uint8_t unsigned int #...
  • C++中多态实现原理

    2019-10-20 16:21:57
    多态是C++面向对象的三大特征之一。 首先说一下多态的分类。 多态分为静态多态和动态多态。函数重载就是属于静态多态。 接下来说一下动态多态。 先上一段代码: ...
  • 相信很多人都看过设计模式方面的书,大家有什么体会呢?Bridge,Proxy,Factory这些设计模式都是基于抽象类的。...由于C++语言本身实现了继承和多态,使用这样的编程理念(理念啥意思?跟个风,嘿嘿)在C++中...
  • 2020-06-091、 概述C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interface其实就是struct,查找Interface的...
  • C语言实现(封装、继承和多态

    万次阅读 多人点赞 2019-02-16 18:46:00
    这个最简单了,C语言中虽然没有类,但有struct。这可是个好东西。我们可以在一个struct中存入数据和函数指针,以此来模拟类行为。 typedef struct _Parent { int a; int b; void (*print)(struct _Parent *This)...
  • C++深度解析 C++对象模型分析(下) --- 继承对象模型,多态对象模型,虚函数表,用C语言实现多态(50)       继承对象模型 在C++编译器的内部类可以理解为结构体。 子类是由 父类成员 叠加 子类新成员 ...
  • 出处:https://www.cnblogs.com/xgmzhna/p/10934562.html 转载于:https://www.cnblogs.com/legenBlog/p/10945382.html
  • ***利用函数指针实现多态*** 一. 函数指针,指针函数是什么 1. 指针函数   指针函数,首先它是一个函数,并且它的返回值是一个指针。形如: // 返回值为整型指针类型 int* fun2() { int* p = (int*)malloc...
  • C语言实现面向对象编程的第三篇,在前面两篇里面我们已经讨论了C语言实现面向对象的封装与继承,这篇我们了解,面向对象的最后一个特性,多态,顺便了解一下C++中的虚指针与虚表。 一、多态是什么? 多态指的是能够...
  • 关注、星标公众号,不错过精彩内容编排 |strongerHuang微信公众号 | strongerHuang不知道有多少人去了解过语言的发展史,早期C语言的语法功能其实比较简单。随着应...
  • 主要介绍了C#中多态现象和多态的实现方法,较为详细的分析了多态的原理与C#实现多态的方法,以及相关的注意事项,需要的朋友可以参考下
  • 这门课的初衷就是让大家能够从汇编的角度看多态实现的背后原理,在理解原理的基础上我们自己动手实践。 在面试(多态是面试题的高频题目)的过程中,能够做到心中自有丘壑。 自己动手模拟多态原理过程中,去如何...
  • 用C/C++语言这类高级编程语言所编写的程序源码是利用一种叫做“编译原理”的技术,经过一些列的处理步骤,最终转变为汇编指令,再最后翻译机器指令。我们知道计算机只能处理和识别二进制指令,而我们所编写的程序...
  • 多态实现主要分为静态多态和动态多态,静态多态主要是重载(函数重载,运算符重载),在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。举个例子:一个父类类型的指针指向一个 子类...
  • 单向链表 c语言实现

    2021-05-21 08:37:01
    定义(引用百度百科)单链表是一种链式存取的数据结构,用一组地址...场景在实际生产中,有可能在软件启动后,对一些数据进行多态扩容,比如,网卡收发包的时候,从协议栈上产生一个需求的包,需要暂时排队,等网卡把...
  • 多态原理探究

    2019-06-02 21:17:54
    多态 1、存在继承 2、子类重写父类函数 存在虚函数 3、要有父类指针(引用)指向子类对象 class Parent { public: Parent(int a = 0) { this->a = a; } virtual void Print()//1.动手脚 写virtual...
  • C语言实现多态原理:函数指针 何为函数指针?答案:C Programming Language. 能够查阅下,从原理上来讲,就是一个内存地址。跳过去运行相应的代码段。 既然如此,在运行时决定跳到哪个地方去运行特定的代码就...
  • 用struct来模拟实现,因为struct在C和C++中都能可以使用,在C中称为结构体在C++中称为类,但他们的原理是一样的,又因为struct的限定符默认是公有的,在C中没有限定符这个概念,所以用C语言只能
  • 但是为了突出实现原理,所以实现的比较简单,只具备了基本功能,通过这些demo,我们可以从代码层面了解这些机制的运行原理,比如用C实现try-catch机制,用C实现多态机制,用C实现智能指针,用C 实现malloc等等。...
  • 如何用C语言实现类似C++中的多态

    千次阅读 2014-12-12 14:42:13
    先引用一篇博文,讲讲什么是多态: C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言。我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的掌握。 ...
  • C++中的多态原理探究

    2020-04-11 00:22:35
    4、多态案例5、多态的理论基础二、多态原理探究1、多态的实现原理2如何证明vptr指针的存在3、构造函数中能调用虚函数,实现多态吗? 一、多态 1、多态问题抛出 如果子类定义了与父类中原型相同的函数会发生什么? 在...
  • 多态原理 动态绑定和静态绑定 虚基表的注意事项和知识点 虚函数表 多态中的虚函数的调用涉及到了一个虚函数表的知识 #include<iostream> using namespace std; class A { public: virtual void f1...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,436
精华内容 4,574
关键字:

c语言实现多态原理