gpt4 book ai didi

c - 使 C 中的两个对象更加面向对象

转载 作者:行者123 更新时间:2023-12-04 08:01:21 25 4
gpt4 key购买 nike

首先,这只是一个学术问题。我知道 C 不是做 OOP 编程的工作,但这更像是一个学习练习,让初学者了解什么是可能的,什么不是(或者,什么是可能的,但不是一个好主意)。
让我们以以下为起点,我有两个不同的对象,但我想为它们中的每一个提供相同的两种方法:createprint .为了简化问题,我省略了任何错误检查、释放等:

#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),因此它不能被滥用。
您可以轻松添加其他基类或接口(interface),例如 RefCounted 来解决内存管理问题。 i-face 将包含指向析构函数和引用计数本身的指针。其他示例是侵入式链表或二叉树。

关于c - 使 C 中的两个对象更加面向对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66450302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com