- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
首先,这只是一个学术问题。我知道 C 不是做 OOP 编程的工作,但这更像是一个学习练习,让初学者了解什么是可能的,什么不是(或者,什么是可能的,但不是一个好主意)。
让我们以以下为起点,我有两个不同的对象,但我想为它们中的每一个提供相同的两种方法:create
和 print
.为了简化问题,我省略了任何错误检查、释放等:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char* name;
int age;
};
struct Car {
char* make;
char* model;
int year;
};
struct Person* create_person(void)
{
struct Person *new = malloc(sizeof (struct Person));
return new;
}
void print_person(struct Person* person)
{
printf("<Person: %s (%d)>\n", person->name, person->age);
}
struct Car* create_car(void)
{
struct Car *new = malloc(sizeof (struct Car));
return new;
}
void print_car(struct Car* car)
{
printf("<Car: %s - %s (%d)>\n", car->make, car->model, car->year);
}
int main(void)
{
struct Car *car = create_car();
*car = (struct Car) {.make="Chevy", .model="Eldorado", .year=2015};
print_car(car);
struct Person *person = create_person();
*person = (struct Person) {.name="Tom", .age=30};
print_person(person);
}
我认为第一部分是将“方法”分组到结构本身中。那么我们将有:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char* name;
int age;
void (*print)(struct Person*);
};
struct Car {
char* make;
char* model;
int year;
void (*print)(struct Car*);
};
void print_car(struct Car* car);
void print_person(struct Person* person);
struct Person* create_person(void)
{
struct Person *new = malloc(sizeof (struct Person));
return new;
}
void print_person(struct Person* person)
{
printf("<Person: %s (%d)>\n", person->name, person->age);
}
struct Car* create_car(void)
{
struct Car *new = malloc(sizeof (struct Car));
return new;
}
void print_car(struct Car* car)
{
printf("<Car: %s - %s (%d)>\n", car->make, car->model, car->year);
}
int main(void)
{
struct Car *car = create_car();
*car = (struct Car) {.make="Chevy", .model="Eldorado", .year=2015, .print=print_car};
car->print(car);
struct Person *person = create_person();
*person = (struct Person) {.name="Tom", .age=30, .print=print_person};
person->print(person);
}
让它“更像 OOP”的下一步是什么?也许使用预处理器胶水和泛型?这两个对象可能成为最像 OOP 的例子是什么?再说一次,我知道这不是 C 的意义所在,但它更像是一种学习体验。
最佳答案
您可以使用 Linux 内核应用的方法。
OOP 的实现基于使用组合来继承,并将接口(interface)嵌入到新类中。
宏container_of
让我们轻松地在指向类的指针和指向其成员之一的指针之间切换。通常嵌入对象将是类的接口(interface)。查找有关 container_of
的更多详细信息宏见我对其他但相关问题的回答。
https://stackoverflow.com/a/66429587/4989451
这种方法被用来创建一个巨大的复杂的面向对象的软件,即 Linux 内核。
在问题的示例中,Car 和 Person 类使用我们可以称为 struct Printable
的打印接口(interface)。 .我强烈建议在 create_...
中生成完全初始化的对象职能。让它复制所有字符串。此外,您应该添加 destroy_...
释放create_...
分配的资源的方法.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#define container_of(ptr, type, member) \
(type*)(void*)((char*)ptr - offsetof(type, member))
struct Printable {
void (*print)(struct Printable*);
};
struct Person {
char* name;
int age;
struct Printable printable;
};
void print_person(struct Printable *printable) {
struct Person *p = container_of(printable, struct Person, printable);
printf("<Person: %s (%d)>\n", p->name, p->age);
}
struct Person *create_person(char *name, int age) {
struct Person *p = malloc(sizeof *p);
p->name = strdup(name);
p->age = age;
p->printable.print = print_person;
return p;
}
struct Car {
char* make;
char* model;
int year;
struct Printable printable;
};
void print_car(struct Printable *printable) {
struct Car *c = container_of(printable, struct Car, printable);
printf("<Car: %s - %s (%d)>\n", c->make, c->model, c->year);
}
struct Car *create_car(char *make, char *model, int year) {
struct Car *c = malloc(sizeof *c);
c->make = strdup(make);
c->model = strdup(model);
c->year = year;
c->printable.print = print_car;
return c;
}
void print(struct Printable *printable) {
printable->print(printable);
}
int main() {
struct Car *car = create_car("Chevy", "Eldorado", 2015);
struct Person *person = create_person("Tom", 30);
print(&car->printable);
print(&person->printable);
return 0;
}
产生输出:
<Car: Chevy - Eldorado (2015)>
<Person: Tom (30)>
注意函数
print()
获取指向
Printable
的指针界面。该函数不需要知道有关原始类的任何信息。没有使用预处理器。所有 Actor 都是在“图书馆”方面完成的,而不是在客户端。该库初始化 Printable 接口(interface),因此它不能被滥用。
关于c - 使 C 中的两个对象更加面向对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66450302/
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
我正在寻找清理 Grails Controller 代码的方法。在各种 Controller 中我或多或少有相同的逻辑.. 获取对象 检查是否存在 等等.. 是否有建议的方法可以使 Controlle
我真的很喜欢 PHP,因为: _ 易于开发 Web 应用程序(您可以在 10 分钟内设置 LAMP,然后就可以开始了) _ 简单易学 _ 易于部署(您只需要带有 PHP 模块的 Apache) 我真的
我正在尝试使用 mod_rewrite 将我的博客 URL 转换为更适合 SEO 的格式。我所有的文章都存储在一个简单的 MySQL 数据库中。每个博客文章的网址如下所示: http://www.te
我是一名优秀的程序员,十分优秀!