值得将每一份知识都放在一个单独的位置,所以我建议为C语言编写一个“部分可读”的类代码。可以使用简单的宏定义集启用它以用短而标准的字完成。此外,也可以使用一个宏在栈分配对象生命周期开始和结束时调用构造函数和析构函数。
比如说,我们首先将以下通用文件包含到C和C++代码中:
#include <stddef.h>
#include <alloca.h>
#define METHOD_EXPORT(c,n) (*c##_##n)
#define CTOR_EXPORT(c) void (c##_construct)(c* thisPtr)
#define DTOR_EXPORT(c) void (c##_destruct)(c* thisPtr)
#ifdef __cplusplus
#define CL_STRUCT_EXPORT(c)
#define CL_METHOD_EXPORT(c,n) n
#define CL_CTOR_EXPORT(c) c()
#define CL_DTOR_EXPORT(c) ~c()
#define OPT_THIS
#else
#define CL_METHOD_EXPORT METHOD_EXPORT
#define CL_CTOR_EXPORT CTOR_EXPORT
#define CL_DTOR_EXPORT DTOR_EXPORT
#define OPT_THIS void* thisPtr,
#define CL_STRUCT_EXPORT(c) typedef struct c c;\
size_t c##_sizeof();
#endif
#define EXPORT_SIZEOF_IMPL(c) extern "C" size_t c##_sizeof() {return sizeof(c);}
#define CTOR_ALIAS_IMPL(c) extern "C" CTOR_EXPORT(c) {new(thisPtr) c();}
#define DTOR_ALIAS_IMPL(c) extern "C" DTOR_EXPORT(c) {thisPtr->~c();}
#define METHOD_ALIAS_IMPL(c,n,res_type,args) \
res_type METHOD_EXPORT(c,n) args = \
call_method(&c::n)
#ifdef __cplusplus
template<class T, class M, M m, typename R, typename... A> R call_method(
T* currPtr, A... args)
{
return (currPtr->*m)(args...);
}
#endif
#define OBJECT_SCOPE(t, v, body) {t* v = alloca(t##_sizeof()); t##_construct(v); body; t##_destruct(v);}
现在我们可以声明我们的类(头文件在C和C++中也很有用)。
#ifdef __cplusplus
class myClass {
private:
int y;
public:
#endif
CL_STRUCT_EXPORT(myClass)
void CL_METHOD_EXPORT(myClass,magic) (OPT_THIS int c);
CL_CTOR_EXPORT(myClass);
CL_DTOR_EXPORT(myClass);
#ifdef __cplusplus
};
#endif
以下是C++中的类实现:
myClass::myClass() {std::cout << "myClass constructed" << std::endl;}
CTOR_ALIAS_IMPL(myClass);
myClass::~myClass() {std::cout << "myClass destructed" << std::endl;}
DTOR_ALIAS_IMPL(myClass);
void myClass::magic(int n) {std::cout << "myClass::magic called with " << n << std::endl;}
typedef void (myClass::* myClass_magic_t) (int);
void (*myClass_magic) (myClass* ptr, int i) =
call_method<myClass,myClass_magic_t,&myClass::magic,void,int>;
这是一个使用C代码的示例
main () {
OBJECT_SCOPE(myClass, v, {
myClass_magic(v,178);
})
}
这很简短且有效!(以下是输出结果)
myClass constructed
myClass::magic called with 178
myClass destructed
请注意,此处使用了可变参数模板,需要使用C++11。但是,如果您不想使用它,则可以使用一些固定大小的模板代替。
magic()
函数中的类对象是否会进行任何内存分配?或者你只关心类本身的大小分配? - RyanPstatic_assert(sizeof(TheClassW) == sizeof(TheClass))
。 - user253751