C语言实现面向对象 #
这里主要介绍下在C语言中是如何实现面向对象的。知道了C语言实现面向对象的方式,再联想一下,C++中的class
的运行原理是什么?
C++中的class
示例
#
首先看一段C++的class
,拿一个Student
类来举例:
头文件(studentpp.h
)
#
#pragma once
class Student {
public:
void SetNumber(int number);
void SetGrade(int grade);
void Print();
private:
int number;
int grade;
};
源文件(studentpp.cpp
)
#
#include "studentpp.h"
#include <stdio.h>
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 \n", this->number, this->grade); }
使用Student
类
#
#include <iostream>
#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.h
)
#
#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;
};
我把它放在了源文件中,在源文件中定义它,再实现相关的方法。
源文件(student.c
)
#
#include "student.h"
#include <stdlib.h>
#include <stdio.h>
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 \n", student->number, student->grade);
}
使用C语言实现的Student
#
#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语言实现多态呢?