多级继承递归 我有一个必须在C中的项目(只是为了避免使用C++参数)。

多级继承递归 我有一个必须在C中的项目(只是为了避免使用C++参数)。,c,inheritance,C,Inheritance,该项目依赖于虚拟表和指针来实现多态性 然而,我一直在从多级继承实现超级构造函数 一个示例结构是: Base Object /\ /\ Constructed Object Simple Object /\ SpecificConstructed 所有对象都有一个名称和一个类。 例如,构造的对象可能具有子对象列表。 因为简单对象只能添加一个值 基本对象仅定义为: struct _object { struct

该项目依赖于虚拟表和指针来实现多态性

然而,我一直在从多级继承实现超级构造函数

一个示例结构是:

            Base Object
            /\       /\
Constructed Object       Simple Object
   /\
SpecificConstructed
所有对象都有一个名称和一个类。 例如,构造的对象可能具有子对象列表。 因为简单对象只能添加一个值

基本对象仅定义为:

struct _object {
     struct _class *class;
     char *name;
}
类是虚拟表所在的位置:

struct _class {
     struct _class *super;
     char *name;
     size_t size;
     void* (*init)(void *_this, char *name);
     ...
}
构造对象是:

struct _constructed_object {
    struct _object base;
    void* components; //a list of sub objects for example
}
 struct _simple_object {
    struct _object base;
    unsigned char value; //a simple value for this specific type
 }
简单对象示例如下:

struct _constructed_object {
    struct _object base;
    void* components; //a list of sub objects for example
}
 struct _simple_object {
    struct _object base;
    unsigned char value; //a simple value for this specific type
 }
所以每个对象都有一个类,类可以有超类,特别是对于SpecificConstructed->Constructed

我的定义如下:

 struct _class base = {0, "Base", sizeof(struct _object), base_init};
 struct _class constructed = {&base, "Constructed", sizeof(struct _constructed_object}, constructed_init};
 struct _class specific = {&constructed, "SpecificConstructed", sizeof(struct _constructed_object), specific_init};
 struct _class simple = {&base, "SimpleOBject", sizeof(struct _simple_object}, simple_init};
此定义允许我使用函数创建指定类的对象:

new(struct _class *a_class) {
    ...
    struct _object *o = calloc(1, a_class->size);
    o->class = a_class;
    o = a_class->init(o);
    return o;
}
如果我这样做的话:

 new(SpecificConstructed)
New将创建适当的空间(sizeof(struct _constructed _object)),它将调用“specific _init”,这反过来将调用“constructed _init”(它是super),最后将调用“base _init”(它是super)。然而,流是特定的、构造的、特定的、构造的

我用于调用超级初始值设定项的函数:

void* super_init(void* _this, char *name){
    struct _object *o = (struct _object*)_this;
    const struct _class *c = o->class;
    const struct _class *s = c->super;
    return (s && s->init) ? s->init(_this, name) : _this;
}
简单的(to-super)基方法调用可以工作,因为我可以只调用supersinit

但是对于特定的构造,调用super会将我带到构造的对象,这是正确的步骤,但是它不会将我发送到base_init,而是将我发送回特定的_init调用。这是因为我传递了相同的_This对象,该对象以特定于类的开始,我理解这一点,但不确定如何修复它,以及是否确实可以修复它


我读过面向对象的C语言书,但它涉及到一级继承循环->点,而元类一章就在我脑海中飞过。IVE也查看Objto-C运行时,看看它是如何处理的,但它也有元类,我现在还不能理解。

< P>这是非常棒的东西,我在90年代初在C中做了一点那种东西,然后转到C++。 不幸的是,尽管你的问题很长,但它仍然有点模糊,因为它没有向我们展示某些东西,比如什么是“构造对象”(为什么这样称呼它),“构造对象”和“简单对象”之间的区别是什么,以及“简单->基本方法调用”是什么。还有,为什么
尺寸
?此外,我认为有必要提供一些示例代码来说明构造函数调用的实际问题

关于这个设计,我现在可以告诉你的一件事是,在虚拟方法表中存储一个指向构造函数的指针,这让我感到奇怪。在我所知道的所有面向对象语言中,(C++、Java、C#)构造函数从来都不是虚拟的;它们看起来更像“静态”方法,用C语言来说,它们只是简单的按名称链接方法。这很好,因为每个类都有内置的、绝对确定的、不变的关于其基类是谁的知识

无论如何,链式构造函数调用应该是这样发生的:

void basemost_init( struct basemost* this, char* name )
{
    this->class = &basemost_class;
    this->name = name;
    ...
}

void intermediate_init( struct intermediate* this, char* name )
{
    basemost_init( &this->base, name );
    this->class = &intermediate_class;
    ...
}

void descendant_init( struct descendant* this, char* name )
{
    intermediate_init( &this->base, name );
    this->class = &descendant_class;
    ...
}
编辑(经过一些澄清)

如果你想让它在分配端看起来很酷,也许可以尝试这样的方法:(我不确定我对C语法的记忆有多好,所以请原谅任何小的错误。)

这样,您就不再需要
尺寸了。另外,请注意,您可以按照需要传递尽可能多的构造函数参数,而不限于固定的、预定数量的参数(我认为这是非常重要的),而不必使用变量构造函数。


如果您承诺使用一致的命名,那么您也可以使用
#define
宏为所有类实现相同的功能,这样每个构造函数的名称都可以计算为
structname##u init
,但我不知道如何在C中的
this
指针之后通过宏传递任意构造函数参数。无论如何,我宁愿避免使用宏,除非它们是绝对必要的,在这种情况下它们不是。

super\u init
不能这样工作,它需要调用super的类,否则(正如您所发现的)直接超类构造函数最终会一遍又一遍地调用自己。因为每个类都知道自己的父类,所以它可以直接调用超类的init。例如,
simple.init
将调用
specific.init
,后者将依次调用
constructed.init
,依此类推


如果你坚持要一个函数来为你做这件事,你必须给它一个类,这样它就可以(很简单)调用超类的构造函数。就是这种设计的一个例子。Python 3引入了一种更易于使用的
super
,但它需要编译器的支持来找出要传递给底层函数的正确类。

不太清楚
struct\u class
的实现应该如何工作ass有自己的一套方法,它们的签名也不同。一个一刀切的结构类如何解决这个问题呢?你想要多重继承还是多重继承还不是很清楚。我的意思是多重继承而不是多重继承,我的错。我对这个问题做了一些编辑,hope it有帮助。我使用OOC手册中使用的方法,其思想是每个类都有一个指向对象使用的初始化器的指针。每个类初始化对象。大小允许我做:new(struct_class)->这将malloc实例的适当大小,然后对其调用init。“每个类都有一个指向对象使用的初始值设定项的指针”这是一个坏主意,而OOC是一本糟糕且误导的书。他们在类描述符中放入
init
,这样他们就可以为
new