
C语言通过结构体和访问控制函数实现封装,通常将结构体定义放在.c文件中隐藏实现细节,头文件只声明结构体指针和操作函数。
头文件(encapsulation.h):
#ifndef ENCAPSULATION_H
#define ENCAPSULATION_H
// 前向声明,隐藏结构体细节
typedef struct Person Person;
// 构造函数
Person* Person_create(const char* name, int age);
// 析构函数
void Person_destroy(Person* person);
// 访问器函数
const char* Person_getName(Person* person);
int Person_getAge(Person* person);
// 修改器函数
void Person_setAge(Person* person, int age);
// 成员函数
void Person_greet(Person* person);
#endif // ENCAPSULATION_H实现文件(encapsulation.c):
#include "encapsulation.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 结构体定义在.c文件中,外部无法直接访问成员
struct Person {
char name[50];
int age;
};
Person* Person_create(const char* name, int age) {
Person* person = (Person*)malloc(sizeof(Person));
if (person) {
strncpy(person->name, name, sizeof(person->name) - 1);
person->name[sizeof(person->name) - 1] = '\0';
person->age = age;
}
return person;
}
void Person_destroy(Person* person) {
free(person);
}
const char* Person_getName(Person* person) {
return person ? person->name : NULL;
}
int Person_getAge(Person* person) {
return person ? person->age : -1;
}
void Person_setAge(Person* person, int age) {
if (person) {
person->age = age;
}
}
void Person_greet(Person* person) {
if (person) {
printf("Hello, I'm %s, %d years old.\n", person->name, person->age);
}
}C++通过class关键字和访问修饰符(public/private/protected)直接支持封装。
#include <iostream>
#include <string>
class Person {
private:
std::string name;
int age;
public:
// 构造函数
Person(const std::string& name, int age) : name(name), age(age) {}
// 析构函数
~Person() {}
// 访问器
std::string getName() const { return name; }
int getAge() const { return age; }
// 修改器
void setAge(int age) { this->age = age; }
// 成员函数
void greet() const {
std::cout << "Hello, I'm " << name << ", " << age << " years old." << std::endl;
}
};C语言通过结构体嵌套模拟继承,派生结构体包含基结构体作为第一个成员,实现成员的"继承"。
头文件(inheritance.h):
#ifndef INHERITANCE_H
#define INHERITANCE_H
#include "encapsulation.h"
// 派生类:Student "继承" Person
typedef struct Student Student;
Student* Student_create(const char* name, int age, const char* major);
void Student_destroy(Student* student);
const char* Student_getMajor(Student* student);
void Student_study(Student* student);
#endif // INHERITANCE_H实现文件(inheritance.c):
#include "inheritance.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 派生结构体包含基结构体作为第一个成员
struct Student {
Person person; // "基类"部分
char major[50]; // 派生类特有成员
};
Student* Student_create(const char* name, int age, const char* major) {
Student* student = (Student*)malloc(sizeof(Student));
if (student) {
// 初始化"基类"部分(模拟构造函数调用)
Person* person = &student->person;
// 这里简化处理,实际应调用基类构造函数逻辑
strncpy(person->name, name, sizeof(person->name) - 1);
person->name[sizeof(person->name) - 1] = '\0';
person->age = age;
strncpy(student->major, major, sizeof(student->major) - 1);
student->major[sizeof(student->major) - 1] = '\0';
}
return student;
}
void Student_destroy(Student* student) {
free(student); // 释放整个结构体,包括"基类"部分
}
const char* Student_getMajor(Student* student) {
return student ? student->major : NULL;
}
void Student_study(Student* student) {
if (student) {
// 通过"基类"指针调用基类方法
printf("%s is studying %s.\n", Person_getName(&student->person), student->major);
}
}C++通过class Derived : public Base语法直接支持继承。
#include <iostream>
#include <string>
#include "person.h" // 假设Person类定义在此
class Student : public Person {
private:
std::string major;
public:
// 构造函数,调用基类构造函数
Student(const std::string& name, int age, const std::string& major)
: Person(name, age), major(major) {}
// 派生类特有方法
std::string getMajor() const { return major; }
void study() const {
std::cout << getName() << " is studying " << major << "." << std::endl;
}
};C语言通过函数指针和结构体组合模拟多态,基类定义函数指针接口,派生类实现具体函数并赋值给基类指针。
头文件(polymorphism.h):
#ifndef POLYMORPHISM_H
#define POLYMORPHISM_H
#include <stdio.h>
// 基类:Shape
typedef struct Shape Shape;
struct Shape {
// 函数指针表(模拟虚函数表)
void (*draw)(Shape* self);
void (*destroy)(Shape* self);
};
// 派生类:Circle
typedef struct Circle Circle;
struct Circle {
Shape shape; // 继承基类
int x, y; // 圆心坐标
int radius; // 半径
};
// 派生类:Rectangle
typedef struct Rectangle Rectangle;
struct Rectangle {
Shape shape; // 继承基类
int x, y; // 左上角坐标
int width; // 宽度
int height; // 高度
};
// 构造函数
Shape* Circle_create(int x, int y, int radius);
Shape* Rectangle_create(int x, int y, int width, int height);
#endif // POLYMORPHISM_H实现文件(polymorphism.c):
#include "polymorphism.h"
#include <stdlib.h>
// Circle实现
static void Circle_draw(Shape* self) {
Circle* circle = (Circle*)self; // 类型转换
printf("Drawing Circle at (%d,%d) with radius %d\n",
circle->x, circle->y, circle->radius);
}
static void Circle_destroy(Shape* self) {
free(self);
}
Shape* Circle_create(int x, int y, int radius) {
Circle* circle = (Circle*)malloc(sizeof(Circle));
if (circle) {
// 初始化基类函数指针(绑定虚函数)
circle->shape.draw = Circle_draw;
circle->shape.destroy = Circle_destroy;
// 初始化派生类成员
circle->x = x;
circle->y = y;
circle->radius = radius;
}
return (Shape*)circle; // 返回基类指针
}
// Rectangle实现
static void Rectangle_draw(Shape* self) {
Rectangle* rect = (Rectangle*)self; // 类型转换
printf("Drawing Rectangle at (%d,%d), width %d, height %d\n",
rect->x, rect->y, rect->width, rect->height);
}
static void Rectangle_destroy(Shape* self) {
free(self);
}
Shape* Rectangle_create(int x, int y, int width, int height) {
Rectangle* rect = (Rectangle*)malloc(sizeof(Rectangle));
if (rect) {
// 初始化基类函数指针(绑定虚函数)
rect->shape.draw = Rectangle_draw;
rect->shape.destroy = Rectangle_destroy;
// 初始化派生类成员
rect->x = x;
rect->y = y;
rect->width = width;
rect->height = height;
}
return (Shape*)rect; // 返回基类指针
}
// 多态演示
void draw_shapes(Shape* shapes[], int count) {
for (int i = 0; i < count; i++) {
shapes[i]->draw(shapes[i]); // 动态调用对应类型的draw方法
}
}C++通过virtual关键字和动态绑定实现多态,编译器自动维护虚函数表(vtable)。
#include <iostream>
// 基类
class Shape {
public:
virtual void draw() const = 0; // 纯虚函数
virtual ~Shape() = default; // 虚析构函数
};
// 派生类:Circle
class Circle : public Shape {
private:
int x, y;
int radius;
public:
Circle(int x, int y, int radius) : x(x), y(y), radius(radius) {}
// 重写虚函数
void draw() const override {
std::cout << "Drawing Circle at (" << x << "," << y
<< ") with radius " << radius << std::endl;
}
};
// 派生类:Rectangle
class Rectangle : public Shape {
private:
int x, y;
int width, height;
public:
Rectangle(int x, int y, int width, int height)
: x(x), y(y), width(width), height(height) {}
// 重写虚函数
void draw() const override {
std::cout << "Drawing Rectangle at (" << x << "," << y
<< "), width " << width << ", height " << height << std::endl;
}
};
// 多态演示
void draw_shapes(const Shape* shapes[], int count) {
for (int i = 0; i < count; i++) {
shapes[i]->draw(); // 动态绑定到实际类型
}
}override关键字和RTTI(运行时类型信息)提供类型安全,C语言需手动确保类型转换正确。特性 | C语言实现方式 | C++实现方式 | 底层共性原理 |
|---|---|---|---|
封装 | 不透明指针+访问函数 | class + public/private/protected | 数据隐藏+接口暴露 |
继承 | 结构体嵌套(基类成员作为首成员) | class Derived : public Base | 内存布局叠加+成员复用 |
多态 | 函数指针表+基类指针强制转换 | virtual函数 + 虚函数表(vtable) | 动态绑定+接口统一实现各异 |
通过上述对比可见,C++的面向对象特性本质上是对C语言模拟技巧的编译器级封装,简化了开发者的实现复杂度并提高了代码安全性。
</content>## 五、使用示例与编译运行
#include "encapsulation.h"
#include "inheritance.h"
#include "polymorphism.h"
int main() {
// 1. 封装示例
printf("=== 封装示例 ===\n");
Person* person = Person_create("Alice", 25);
Person_greet(person);
printf("Name: %s\n", Person_getName(person));
printf("Age: %d\n", Person_getAge(person));
Person_setAge(person, 26);
printf("Updated Age: %d\n", Person_getAge(person));
Person_destroy(person);
// 2. 继承示例
printf("\n=== 继承示例 ===\n");
Student* student = Student_create("Bob", 20, "Computer Science");
// 通过基类方法访问继承的成员
Person_greet(&student->person);
// 调用派生类特有方法
printf("Major: %s\n", Student_getMajor(student));
Student_study(student);
Student_destroy(student);
// 3. 多态示例
printf("\n=== 多态示例 ===\n");
Shape* shapes[2];
shapes[0] = Circle_create(10, 20, 5);
shapes[1] = Rectangle_create(30, 40, 20, 15);
draw_shapes(shapes, 2);
// 销毁对象
shapes[0]->destroy(shapes[0]);
shapes[1]->destroy(shapes[1]);
return 0;
}#include "person.h"
#include "student.h"
#include "shape.h"
#include "circle.h"
#include "rectangle.h"
#include <vector>
int main() {
// 1. 封装示例
std::cout << "=== 封装示例 ===" << std::endl;
Person person("Alice", 25);
person.greet();
std::cout << "Name: " << person.getName() << std::endl;
std::cout << "Age: " << person.getAge() << std::endl;
person.setAge(26);
std::cout << "Updated Age: " << person.getAge() << std::endl;
// 2. 继承示例
std::cout << "\n=== 继承示例 ===" << std::endl;
Student student("Bob", 20, "Computer Science");
student.greet(); // 继承自Person
std::cout << "Major: " << student.getMajor() << std::endl;
student.study(); // 派生类特有方法
// 3. 多态示例
std::cout << "\n=== 多态示例 ===" << std::endl;
std::vector<Shape*> shapes;
shapes.push_back(new Circle(10, 20, 5));
shapes.push_back(new Rectangle(30, 40, 20, 15));
for (const auto* shape : shapes) {
shape->draw(); // 动态绑定
}
// 清理内存
for (auto* shape : shapes) {
delete shape;
}
return 0;
}# 编译所有源文件
gcc -c encapsulation.c -o encapsulation.o
gcc -c inheritance.c -o inheritance.o
gcc -c polymorphism.c -o polymorphism.o
gcc -c main.c -o main.o
# 链接生成可执行文件
gcc encapsulation.o inheritance.o polymorphism.o main.o -o oop_demo_c
# 运行
./oop_demo_c# 编译并链接
g++ main.cpp person.cpp student.cpp shape.cpp circle.cpp rectangle.cpp -o oop_demo_cpp
# 运行
./oop_demo_cpp=== 封装示例 ===
Hello, I'm Alice, 25 years old.
Name: Alice
Age: 25
Updated Age: 26
=== 继承示例 ===
Hello, I'm Bob, 20 years old.
Major: Computer Science
Bob is studying Computer Science.
=== 多态示例 ===
Drawing Circle at (10,20) with radius 5
Drawing Rectangle at (30,40), width 20, height 15=== 封装示例 ===
Hello, I'm Alice, 25 years old.
Name: Alice
Age: 25
Updated Age: 26
=== 继承示例 ===
Hello, I'm Bob, 20 years old.
Major: Computer Science
Bob is studying Computer Science.
=== 多态示例 ===
Drawing Circle at (10,20) with radius 5
Drawing Rectangle at (30,40), width 20, height 15通过亲手实现这三大特性,能更深入理解面向对象编程的本质,以及不同语言实现机制的异同。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。