1 怎么用C语言实现多态-德赢Vwin官网 网

怎么用C语言实现多态

描述

这里我想主要介绍下在C语言中是如何实现的面向对象。知道了C语言实现面向对象的方式,我们再联想下,C++中的class的运行原理是什么?

首先我们来写一段C++的class,拿一个Student类来举例子:

在头文件中,我定义一个Student类:

 

#pragma once
class Student {
public:
  void SetNumber(int number);
  void SetGrade(int grade);
  void Print();
private:
  int number;
  int grade;
};

 

再在源文件中实现它:

 

#include "studentpp.h"
#include 
void Student::SetNumber(int number) { this->number = number; }
void Student::SetGrade(int grade) { this->grade = grade; }
void Student::Print() { printf("studentpp number : %d, grade : %d 
", this->number, this->grade);}

 

接下来是使用Student类:

 

#include 
#include "studentpp.h"
int main() {
  Student *stu1 = new Student;
  Student *stu2 = new Student;
  stu1->SetNumber(11);
  stu2->SetNumber(22);
  stu1->SetGrade(111);
  stu2->SetGrade(222);
  stu1->Print();
  stu2->Print();
  delete stu1;
  delete stu2;
}

 

我们再运行一下,运行结果不出所料。

那你有没有想过,它的底层是怎么实现的?为什么不同对象,设置了不同的number和grade,它的输出却不一样?

这个问题我们先放在这。等我用C语言实现一套这种方案后,估计你就明白了。

首先,在头文件中定义一个C语言的结构体Student:

 

#pragma once
typedef struct Student Student;
Student* CreateStudent();
void DestroyStudent(Student* student);
void SetNumber(Student* student, int number);
void SetGrade(Student* student, int grade);
void Print(Student* student);

 

注意在这里我使用了一个typedef,即Student = struct Student;

但是我却没有在头文件中定义它:

 

struct Student {
  int number;
  int grade;
};

 

我把它放在了源文件中,在源文件中定义它,再实现相关的方法。

 

#include "student.h"
#include 
#include 

struct Student {
  int number;
  int grade;
};

Student* CreateStudent() {
  Student* self = (Student*)malloc(sizeof(Student));
  return self;
}

void DestroyStudent(Student* student) {
  if (!student) return;
  free((void*)student);
}

void SetNumber(Student* student, int number) {
  if (!student) return;
  student->number = number;
}

void SetGrade(Student* student, int grade) {
  if (!student) return;
  student->grade = grade;
}

void Print(Student* student) {
  if (!student) return;
  printf("student number : %d, grade : %d 
", student->number, student->grade);
}

 

然后使用它:

 

#include "student.h"

int main() {
  Student* stu1 = CreateStudent();
  Student* stu2 = CreateStudent();
  SetNumber(stu1, 11);
  SetNumber(stu2, 22);
  SetGrade(stu1, 111);
  SetGrade(stu2, 222);
  Print(stu1);
  Print(stu2);
  DestroyStudent(stu1);
  DestroyStudent(stu2);
}

 

这是不是面向对象的原理?数据封装到了不同的指针下,不同的指针传到了相同的函数中,行为也会不同。

这时候我们再联想一下C++中的面向对象是不也是这个原理

平时我们使用的:

 

a->Print();

 

其实它的原理可能是这样的:

 

void Print(Student* this) {
  this->number;
  this->grade;
}

 

只不过编译器把默认的这个this参数隐藏在内部,我们看不见而已。其实每个成员函数默认都会有一个参数,就是对象的指针,也就是this指针。到这里你应该也就明白面向对象的原理了吧。

注意在这里我使用了一个typedef,即Student = struct Student;

但是我却没有在头文件中定义它。

这样可以更好的隐藏Student的实现,外面不知道Student究竟是什么东西,只有内部知道。在头文件中对外只暴露Student的指针,然后指针传到源文件中,再去解析它。

比如,我在其它地方想要得到Student的大小,编译器会报错,没法使用sizeof,因为它不知道Student,它只知道它是不完整的类型。而只能在源文件中使用sizeof。

这种设计是不是比C++的class更安全一些,确实安全,其实C++也可以这样实现,就是可以使用pImpl指针。

pimpl我暂时先不介绍,大家可以自己研究一下(其实历史文章中介绍过)。

大家可以思考下,怎么用C语言实现多态呢?  

      审核编辑:彭静
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分
vConsole
Object {abort: [object Function], always: [...
GET <script> error: https://zz.bdstatic.com/linksubmit/push.js
Uncaught SyntaxError: Unexpected token '<' /gtag/js?id=G-QS9R4LMEKM:1:1 SyntaxError: Unexpected token '<'
      Location: https://www.hzfubeitong.com/m/article/1903467.html
      Client: Unknown
      UA: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
      navigationStart: 1736876026764
      navigation: 613ms
      dns: 92ms
      tcp (ssl): 124ms (64ms)
      request: 2438ms
      response: 1ms
      Name (5)
      Method
      Status
      Time
      getListByPlaAndLoc
      POST
      0
      77
      General
      URL
      https://advert-server.elecfans.com/api/advert/getListByPlaAndLoc
      Method
      POST
      Type
      xhr
      Request Headers
      X-Requested-With
      XMLHttpRequest
      Content-type
      application/x-www-form-urlencoded;charset=UTF-8
      Request Payload
      platform
      elecfans
      location
      47
      user_id
      0
      status
      1
      page
      1
      limit
      100
      url
      https://www.hzfubeitong.com/m/article/1903467.html
      tag_id
      5433,19067,131914
      Response
            
      getListByPlaAndLoc
      POST
      0
      164
      General
      URL
      https://advert-server.elecfans.com/api/advert/getListByPlaAndLoc
      Method
      POST
      Type
      xhr
      Request Headers
      Content-Type
      application/x-www-form-urlencoded; charset=UTF-8
      Accept
      */*
      Request Payload
      platform
      elecfans
      location
      73
      user_id
      0
      status
      1
      page
      1
      limit
      100
      url
      https%3A%2F%2Fwww.hzfubeitong.com%2Fm%2Farticle%2F1903467.html
      tag_id
      5433%2C19067%2C131914
      Response
            
      arcinfo?dopost=arcinfo&aid=1903467
      GET
      Pending
      0
      General
      URL
      https://www.hzfubeitong.com/webapi/arcinfo?dopost=arcinfo&aid=1903467
      Method
      GET
      Type
      xhr
      Request Headers
      Accept
      application/json, text/javascript, */*; q=0.01
      X-Requested-With
      XMLHttpRequest
      Query String Parameters
      dopost
      arcinfo
      aid
      1903467
      Response
            
      getSchooleList
      POST
      Pending
      0
      General
      URL
      /home/Article/getSchooleList
      Method
      POST
      Type
      xhr
      Request Headers
      Accept
      */*
      Request Payload
      [object Object]
      Response
            
      getList?aid=1903467&page=1
      GET
      Pending
      0
      General
      URL
      /comment/getList?aid=1903467&page=1
      Method
      GET
      Type
      xhr
      Request Headers
      Accept
      application/json, text/javascript, */*; q=0.01
      X-Requested-With
      XMLHttpRequest
      Query String Parameters
      aid
      1903467
      page
      1
      Response
            
      Key
      Value
      Empty