C语言是一种面向过程的语言,但是也可以用结构体和函数指针来模拟面向对象的特性,比如封装、继承和多态。下面我们来看一些具体的例子和应用。
封装是指把对象的属性和方法封装在一起,提供一个接口给外部调用,隐藏内部细节。在C语言中,我们可以用结构体来定义对象的属性,用函数指针来定义对象的方法,然后把它们放在一个结构体中,形成一个类。例如,我们可以定义一个人类:
#include <stdio.h>
#include <stdlib.h>
// 定义人类
struct person {
// 属性
char *name;
int age;
// 方法
void (*say_hello)(struct person *p);
};
// 定义人类的方法
void say_hello(struct person *p) {
printf("Hello, I am %s, %d years old.\n", p->name, p->age);
}
// 创建人类的实例
struct person *create_person(char *name, int age) {
struct person *p = malloc(sizeof(struct person));
p->name = name;
p->age = age;
p->say_hello = say_hello;
return p;
}
// 使用人类的实例
int main() {
struct person *p1 = create_person("Alice", 20);
struct person *p2 = create_person("Bob", 25);
p1->say_hello(p1);
p2->say_hello(p2);
free(p1);
free(p2);
return 0;
}
继承是指子类可以复用父类的属性和方法,同时可以添加或覆盖父类的属性和方法。在C语言中,我们可以用结构体嵌套来实现继承,即把父类作为子类的第一个成员。例如,我们可以定义一个学生类,继承自人类:
#include <stdio.h>
#include <stdlib.h>
// 定义人类
struct person {
// 属性
char *name;
int age;
// 方法
void (*say_hello)(struct person *p);
};
// 定义人类的方法
void say_hello(struct person *p) {
printf("Hello, I am %s, %d years old.\n", p->name, p->age);
}
// 创建人类的实例
struct person *create_person(char *name, int age) {
struct person *p = malloc(sizeof(struct person));
p->name = name;
p->age = age;
p->say_hello = say_hello;
return p;
}
// 定义学生类
struct student {
// 继承自人类
struct person base;
// 属性
char *school;
// 方法
void (*study)(struct student *s);
};
// 定义学生类的方法
void study(struct student *s) {
printf("%s is studying at %s.\n", s->base.name, s->school);
}
// 创建学生类的实例
struct student *create_student(char *name, int age, char *school) {
struct student *s = malloc(sizeof(struct student));
s->base.name = name;
s->base.age = age;
s->base.say_hello = say_hello; // 复用父类的方法
s->school = school;
s->study = study;
return s;
}
// 使用学生类的实例
int main() {
struct student *s1 = create_student("Charlie", 18, "MIT");
struct student *s2 = create_student("David", 19, "Stanford");
s1->base.say_hello(&s1->base); // 调用父类的方法
s2->base.say_hello(&s2->base);
s1->study(s1); // 调用子类的方法
s2->study(s2);
free(s1);
free(s2);
return 0;
}
多态是指不同类型的对象可以使用相同的接口,根据对象的具体类型执行不同的行为。在C语言中,我们可以用函数指针来实现多态,即把不同类型的对象都转换为一个通用类型,然后调用它们共有的函数指针。例如,我们可以定义一个动物类和两个子类:狗类和猫类,分别实现动物类的叫声方法:
#include <stdio.h>
#include <stdlib.h>
// 定义动物类
struct animal {
// 属性
char *name;
// 方法
void (*make_sound)(struct animal *a);
};
// 定义狗类
struct dog {
// 继承自动物类
struct animal base;
// 属性
char *breed;
};
// 定义猫类
struct cat {
// 继承自动物类
struct animal base;
// 属性
char *color;
};
// 定义动物类的方法
void make_sound(struct animal *a) {
printf("%s is making sound.\n", a->name);
}
// 定义狗类的方法
void dog_make_sound(struct dog *d) {
printf("%s is barking.\n", d->base.name);
}
// 定义猫类的方法
void cat_make_sound(struct cat *c) {
printf("%s is meowing.\n", c->base.name);
}
// 创建动物类的实例
struct animal *create_animal(char *name) {
struct animal *a = malloc(sizeof(struct animal));
a->name = name;
a->make_sound = make_sound;
return a;
}
// 创建狗类的实例
struct dog *create_dog(char *name, char *breed) {
struct dog *d = malloc(sizeof(struct dog));
d->base.name = name;
d->base.make_sound = (void (*)(struct animal *))dog_make_sound; // 覆盖父类的方法
d->breed = breed;
return d;
}
// 创建猫类的实例
struct cat *create_cat(char *name, char *color) {
struct cat *c = malloc(sizeof(struct cat));
c->base.name = name;
c->base.make_sound = (void (*)(struct animal *))cat_make_sound; // 覆盖父类的方法
c->color = color;
return c;
}
// 使用动物类的实例
int main() {
struct animal *a1 = create_animal("Tom");
struct dog *d1 = create_dog("Spike", "Bulldog");
struct cat *c1 = create_cat("Jerry", "Brown");
// 多态:不同类型的对象使用相同的接口,执行不同的行为
a1->make_sound(a1); // 调用动物类的方法
d1->base.make_sound(&d1->base); // 调用狗类的方法
c1->base.make_sound(&c1->base); // 调用猫类的方法
free(a1);
free(d1);
free(c1);
return 0;
}
以上就是C语言面向对象的一些例子。 |