Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C+的C包装+;库-继承呢? 我已经阅读了,我喜欢这个方法,我用我的库-不透明句柄来处理每个对应的C++类;避免使用void*_C++_C_Inheritance_Wrapper - Fatal编程技术网

C+的C包装+;库-继承呢? 我已经阅读了,我喜欢这个方法,我用我的库-不透明句柄来处理每个对应的C++类;避免使用void*

C+的C包装+;库-继承呢? 我已经阅读了,我喜欢这个方法,我用我的库-不透明句柄来处理每个对应的C++类;避免使用void*,c++,c,inheritance,wrapper,C++,C,Inheritance,Wrapper,但现在,我要考虑“接口”和基类。例如,我有一个“通道”类的类层次结构-一个“通道”的基类和派生的具体类,例如串行通信、内存缓冲区、套接字等 因此,我: typedef struct serial_channel serial_channel; typedef struct socket_channel socket_channel; typedef struct memory_channel memory_channel; serial_channel* create_serial_chann

但现在,我要考虑“接口”和基类。例如,我有一个“通道”类的类层次结构-一个“通道”的基类和派生的具体类,例如串行通信、内存缓冲区、套接字等

因此,我:

typedef struct serial_channel serial_channel;
typedef struct socket_channel socket_channel;
typedef struct memory_channel memory_channel;

serial_channel* create_serial_channel();
socket_channel* create_socket_channel();
memory_channel* create_memory_channel();
但我希望能够将其中任何一个传递到函数中,以将其与“设备”对象关联:

void associate_device_with_channel(device*, channel*);

C++中容易,因为它理解基类。如何在C包装器库中实现这一点-C中的

channel
是什么类型

我唯一能想到的是,我必须诉诸void*来表示一个基类

typedef void* channel;
void associate_device_with_channel(device*, channel*);
它能工作,但能让我传递任何指针吗

另一方面,我可以编写一组与派生通道类匹配的函数:

void associate_device_with_serial_channel(device*, serial_channel*);
void associate_device_with_socket_channel(device*, socket_channel*);
void associate_device_with_memory_channel(device*, memory_channel*);
它非常冗长,如果我必须添加新的通道类型,我还必须向接口添加新函数


有没有我一直缺少的中间立场像单个函数,但不是void*?

没有任何完美的方法。您试图使函数接受一些不透明的句柄(具有适当基类的句柄),但不接受任何句柄类型(这是
void*
可以接受的),而C语言中没有这样的东西

如果愿意,可以提供一个函数,该函数接受
串行通道*
并返回
通道*
,另一个函数用于每个
通道
子类。这使您远离了不安全的C强制转换,并且不需要使用
numfuncs*numderivedclasses
不同的
通道
-获取函数


就我个人而言,我只是想把它作废。毕竟他们用的是C。。。很明显,他们并不太在意语言的安全性。

如果您只针对GCC或Clang(我想如果您针对的是visualstudio,您不会为C而烦恼),您的选择之一是使用非标准的
\uu transparent\u union\uuu
属性创建一个联合,以列出函数可以接受的类型。接受带有
\uuuu transparent\u union\uuu
属性的联合参数的函数将接受该联合或其中包含的任何类型

union associable_channel
{
    channel* a;
    serial_channel* b;
    socket_channel* c;
    memory_channel* d; 
} __attribute__((__transparent_union__));

void associate_device_with_channel(union associable_channel chan);

serial_channel* serial;
socket_channel* socket;
memory_channel* mem;
associate_device_with_channel(serial);
associate_device_with_channel(socket);
associate_device_with_channel(mem);

首先,我会建立这样的结构:

typedef void base_class;
struct base_class_impl
{
    // base class member variables go here
}
struct derived_class
{
    // base class must come first in the derived struct
    struct base_class_impl base;
    // derived class member variables go here
}
然后,我会将指向
base_class
的指针作为函数的参数:

int base_class_get_count(base_class *b);
我总是在活动开始时投下:

int base_class_get_count(base_class *b)
{
    struct base_class *base = (struct base_class *)b;
    // Operate on the object now
}

这使得
base\u class\u get\u count()
甚至可以在派生类型的对象上工作。缺点是它不允许派生类型重写方法-您必须更进一步,实现自己的函数指针表,API将根据表中的条目(如
base\u class\u get\u count
)调用这些指针。

使用单一类型,而不是多个通道类型。当且仅当您需要提供仅适用于特定信道类型的专用功能时,才包括类型代码。在这种情况下,必须在运行时强制执行类型检查。如果将基类(struct)作为继承类(struct)的第一个元素,并利用指向结构对象的指针指向其初始成员的事实,则可以在C中实现继承效果。检查这个答案,例如:“Dabo,他不想在C.做继承。他试图通过不透明的C句柄来公开他的C++继承结构。这是一个很酷的特性,但是我会担心。”代码>\uuuuuu透明\uuuuuuuuuuu在放入
串行通道
和取出
通道
时,不会执行任何指针调整。因此,在存在多重继承的情况下,这可能会悄悄地把事情搞砸。有趣的特性是,这在概念上与为每个成员使用一个非显式联合构造函数相同吗?它只适用于函数参数。例如,您不能执行
union associable\u channel foo=serial
。(好吧,我们谈论的是一个非标准特性,所以很明显,供应商可以让它工作,但这种行为不是用GCC或Clang指定的。)至于多重继承,问题是真实的,但如果OP能够负担得起指向
void*
的C-cast指针,那么透明联合就可以完全安全地替代它(读:在同样的情况下,这将无声地中断)同时保留一些额外的类型表现力。我个人从来不使用多重继承,除了没有字段的接口,我知道我不是唯一一个这样工作的人。不幸的是,我使用的是Visual Studio,所以这对我来说不起作用。但知道这一点非常有用。我不知道多重继承的问题-我明白你的意思你是说,但我不使用MI,所以这对我来说不是问题。谢谢克里斯。调度不是问题,因为它都是C++幕后。最终,你的基类仍然是空洞*。我想显示意图和创建一个代表基本类的Type的方法是有用的,即使它是空洞*。你是对的,它仍然是空洞*。但是,如果你真的那么做了。nt是接受派生类型对象的基类方法,我相信这是C中的唯一方法。否则,必须有一个“god”结构,其中包含所有派生类的所有成员变量(如果它们包含其他成员变量)然后传入该类型-这在某种程度上违背了OO的初衷。void*方法会让您面临意外传入错误对象的情况-编译器在这方面不会帮助您。我认为这是一个可以接受的折衷。是的,在另一个答案中引用Sneftel-“毕竟,他们使用的是C语言……很明显,他们并不太在意语言的安全。”:-)