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语言……很明显,他们并不太在意语言的安全。”:-)