C中的默认构造函数 P>有没有一种方法来构造一个默认的构造函数(例如C++),用结构定义的C用户类型?< /P>
我已经有了一个类似于快速初始值设定项的宏(类似于C中的默认构造函数 P>有没有一种方法来构造一个默认的构造函数(例如C++),用结构定义的C用户类型?< /P>,c,constructor,C,Constructor,我已经有了一个类似于快速初始值设定项的宏(类似于pthread\u mutex),但我想知道您是否可以在声明时填充结构的一些(或全部)字段 例如,对于pthread\u mutex示例,我希望 pthread_mutex_t my_mutex; 与 pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; 不,不是直接的。最接近的方法是编写一个分配实例并填充某些字段的函数。您可以编写一个返回C结构的函数: struct file create
pthread\u mutex
),但我想知道您是否可以在声明时填充结构的一些(或全部)字段
例如,对于pthread\u mutex
示例,我希望
pthread_mutex_t my_mutex;
与
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
不,不是直接的。最接近的方法是编写一个分配实例并填充某些字段的函数。您可以编写一个返回C结构的函数:
struct file create_file(int i, float f) {
struct file obj = { i, f };
// other code here...
return obj;
}
如果你想知道在C中是否可以有“正常”的成员函数,那么,在某种程度上,你可以。我更喜欢对象作为第一个参数样式。将指向结构的指针作为第一个参数传递。通过这种方式,您可以使用多个函数来定义对象的接口:
int file_get_integer(struct file *self) { return self->i; }
float file_get_float(struct file *self) { return self->f; }
如果您以这种风格编写,那么您最后得到的是一种抽象数据类型。我见过通过在函数结构中有函数指针然后在执行:的方法来模拟C++中使用的成员函数调用语法的家伙。
obj.get_integer(&obj);
linux内核使用它来定义文件系统驱动程序的接口。这是一种写作风格,一个人可能喜欢,也可能不喜欢。我不太喜欢它,因为我一直在为数据使用结构成员,而不是像流行的面向对象语言那样模拟成员函数调用。您可以创建带结构指针的初始值设定项函数。这是惯例 还包括创建结构并对其进行初始化(如工厂)的函数,因此在“客户机”代码中从来没有结构“未初始化”的时候。当然-这假设人们遵循惯例并使用“构造函数”/“工厂” 可怕的伪代码,在malloc或free上没有错误检查
somestruct* somestruct_factory(/* per haps some initializer agrs? */)
{
malloc some stuff
fill in some stuff
return pointer to malloced stuff
}
void somestruct_destructor(somestruct*)
{
do cleanup stuff and also free pointer
free(somestruct);
}
可能会有人来解释一些早期的C++预处理器/编译器是如何在C.中执行这一切的,
< P>不,结构只是一堆数据。无法在结构中声明函数,因此无法为其创建构造函数。不太可能。如果我没记错的话,最接近类的是结构。分配内存并填充字段。我不知道你会怎么做一个通用的构造函数类型的东西。理论上,您可以编写一个宏来完成其中的一些操作。不过,不确定这是否真的值得。假设您想在C中实现这一点,那么您的问题不是关于C++中的结构: 我通常做的是创建一个函数init_,不管什么,它接受指向结构(或其他变量)的指针,并将其设置为我想要的值 如果它是一个全局变量(初始化为零),您可以通过在其中设置一个“initialized”标志来模拟一个无参数构造函数,然后让您的其他函数检查该标志,如果该标志为零,则初始化该结构。不过,我一点也不确定这是个好主意和其他人一样,你也可以用宏来做一些可怕的事情……
基本上,C++创建了包含方法地址的指针列表。此列表称为类定义(类定义中还有一些数据,但我们暂时忽略了这些数据) 纯C中有“类”的常见模式是定义“结构类”。结构的一个字段是工厂函数,它返回类的“实例”。我建议使用宏来隐藏强制转换:typedef struct __class * class;
typedef void (*ctor_ptr)(class);
struct class {
char * name;
ctor_ptr ctor;
... destructor and other stuff ...
}
#define NEW(clz) ((struct something *)(((struct class *)clz)->ctor(clz)))
现在,您可以通过为每个类创建“struct class”类型的结构来定义所拥有的类,然后调用其中存储的构造函数。这同样适用于析构函数等
如果需要实例的方法,则必须将它们放入类结构中,并在实例结构中保留指向类的指针:
#define NEW_SOMETHING() ((struct something *)NEW(&something_definition))
#define METHOD(inst, arg) ((struct something_class *)(((struct something *)inst)->clz)->method(inst, arg))
NEW\u SOMETHING
将使用存储在结构SOMETHING\u definition
中的类定义创建“SOMETHING”的新实例。方法将在此实例上调用“方法”。注意,对于真正的代码,您需要检查inst
是否实际上是某物的实例(比较类指针,类似的)
继承有点棘手,留给读者作为练习
<>请注意,在C++中,你可以做C++中的所有事情。C++编译器并没有神奇地用其他东西取代你的CPU。这需要更多的代码来完成
如果您想看一个示例,请查看(Gtk+项目的一部分)。在本例中,C++与C的不同之处在于它没有“类”。然而,C(和许多其他语言一样)仍然可以用于面向对象编程。在这种情况下,构造函数可以是初始化结构的函数。这与构造函数相同(只是语法不同)。另一个区别是,您必须使用malloc()(或某种变体)分配对象。在C++中,你将使用新的操作符。
<> > C++代码:
class A {
public:
A() { a = 0; }
int a;
};
int main()
{
A b;
A *c = new A;
return 0;
}
等效C代码:
struct A {
int a;
};
void init_A_types(struct A* t)
{
t->a = 0;
}
int main()
{
struct A b;
struct A *c = malloc(sizeof(struct A));
init_A_types(&b);
init_A_types(c);
return 0;
}
函数'iNITAYAYTYPE '作为构造函数将在C++中.
您可能想看C++编译器。与试图用库和宏将构造函数等连接到C上相比,它以一种更优雅、更标准的方式为您提供了更多面向对象的特性,这在一种具有类似C的语法的语言中是无法记住的
如果这对你不起作用,那么看看GObject。它是GTK和Gnome中使用的C对象系统,几乎可以将“C中的对象”拖动到11
来自维基百科:
GLib对象系统或GObject是一个自由软件库(由LGPL覆盖),它提供了一个可移植的对象系统和透明的跨语言互操作性。
系统支持构造函数、析构函数、单一继承、接口、虚拟公共和私有方法以及
typedef struct t_ProcessStruct *t_ProcessHandle;
extern t_ProcessHandle NewProcess();
extern void DisposeProcess(t_ProcessHandle handle);
typedef struct t_PermissionsStruct *t_PermissionsHandle;
extern t_PermissionsHandle NewPermissions();
extern void DisposePermissions(t_PermissionsHandle handle);
extern void SetProcessPermissions(t_ProcessHandle proc, t_PermissionsHandle perm);
typedef void (*fDisposeFunction)(void *memoryBlock);
typedef struct {
fDisposeFunction _dispose;
} t_DisposableStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PID _pid;
/* etc */
} t_ProcessStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PERM_FLAGS _flags;
/* etc */
} t_PermissionsStruct;
static void DisposeMallocBlock(void *process) { if (process) free(process); }
static void *NewMallocedDisposer(size_t size)
{
assert(size > sizeof(t_DisposableStruct);
t_DisposableStruct *disp = (t_DisposableStruct *)malloc(size);
if (disp) {
disp->_dispose = DisposeMallocBlock;
}
return disp;
}
static void DisposeUsingDisposer(t_DisposableStruct *ds)
{
assert(ds);
ds->_dispose(ds);
}
t_ProcessHandle NewProcess()
{
t_ProcessHandle proc = (t_ProcessHandle)NewMallocedDisposer(sizeof(t_ProcessStruct));
if (proc) {
proc->PID = NextPID(); /* etc */
}
return proc;
}
void DisposeProcess(t_ProcessHandle proc)
{
DisposeUsingDisposer(&(proc->_disposer));
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define new(TYPE, ...) memdup(&(TYPE){ __VA_ARGS__ }, sizeof(TYPE))
void * memdup(const void * obj, size_t size)
{
void * copy = malloc(size);
return copy ? memcpy(copy, obj, size) : NULL;
}
struct point
{
int x;
int y;
};
int main()
{
int * i = new(int, 1);
struct point * p = new(struct point, 2, 3);
printf("%i %i %i", *i, p->x, p->y);
return 0;
}
struct some_struct {
int a;
float b;
};
#define some_struct_DEFAULT { 0, 0.0f}
struct some_struct *some_struct_create(void) {
struct some_struct *ptr = malloc(sizeof some_struct);
if(!ptr)
return ptr;
*ptr = some_struct_DEFAULT;
return ptr;
}
// (...)
struct some_struct on_stack = some_struct_DEFAULT;
struct some_struct *on_heap = some_struct_create();
#include <stdio.h>
void __attribute__ ((constructor)) default_constructor()
{
printf("%s\n", __FUNCTION__);
}
int main()
{
printf("%s\n",__FUNCTION__);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct somestruct
{
int empid;
char * name;
};
struct somestruct * str1;
void __attribute__ ((constructor)) a_constructor()
{
str1 = (struct somestruct *) malloc (sizeof(struct somestruct));
str1 -> empid = 30228;
str1 -> name = "Nandan";
}
void __attribute__ ((destructor)) a_destructor()
{
free(str1);
}
int main()
{
printf("ID = %d\nName = %s\n", str1 -> empid, str1 -> name);
return 0;
}