我在面向对象编程方面没有太多经验。我正在尝试在c中创建一个具有自己方法的对象。 我已经声明了具有指向函数的指针的结构。该变量的所有实例都将指向相同的函数。但是目前我需要在main(行1和行2)中初始化变量的每个实例。那么有什么方法可以在我声明时初始化它的默认值吗?
#include <stdio.h>
#include <stdlib.h>
typedef struct serialStr Serial;
struct serialStr
{
void(*init)(Serial*);
void(*open)();
void(*close)();
};
void open()
{
printf("Open Port Success\n");
return;
}
void close()
{
printf("Close port Success\n");
return;
}
void init(Serial* ptr)
{
ptr->open = open;
ptr->close = close;
}
int main()
{
Serial serial,serial_2;
serial.init = init;
serial.init(&serial); // Line1
serial_2.init = init;
serial_2.init(&serial_2); // Line2
serial.open();
//rest of code
serial.close();
serial_2.open();
serial_2.close();
return 0;
}
答案 0 :(得分:3)
在C中,标准方法是声明初始化器宏:
#define SERIAL_INITIALIZER { .init = init, .open = open, /* and others */ }
Serial serial = SERIAL_INITIALIZER;
在C的大多数情况下,根本不需要动态初始化变量。您只需要malloc
ed对象。
答案 1 :(得分:1)
C ++通过调用构造函数/析构函数来添加一些自动化。在纯C中是没有办法这样做的。你应该手动完成所有步骤:创建和初始化对象(为结构调用类似构造函数的函数),通过结构实例中的指针调用函数,调用析构函数(它应该销毁实例并释放相关资源)。
如果你的任务中没有多态,那么使用简单的方法 - 没有指向函数的指针,但是每个函数(方法)都应该指向对象。
常见案例:
struct MyStruct
{
// data
};
struct MyStruct* createMyStruct(/* maybe some input */)
{
// create, init and return the structure instance
}
void destoyMyStruct(struct MyStruct* obj)
{
// free resources and delete the instance
}
void doSomeAction(struct MyStruct* obj /* , some other data */)
{
// ...
}
int main()
{
struct MyStruct* object = createMyStruct();
doSomeAction(object);
destoyMyStruct(object);
return 0;
}
编辑1:宏仅适用于非常简单的情况和容易出错的方式。
答案 2 :(得分:0)
通常,您可以通过&#34; opaque类型&#34;来完成此操作。这意味着您在标题中声明了一个不完整类型的对象:
typedef struct Serial Serial;
然后在C文件中放置实际的struct定义。这会将结构的内容隐藏到调用者(私有封装)。然后,您可以从构造函数中设置私有成员函数:
struct Serial
{
void(*init)(void);
void(*open)(void);
void(*close)(void);
};
// private member functions:
static void open (void);
...
// constructor:
Serial* SerialCreate (void)
{
Serial* s = malloc(sizeof (*s));
...
s->open = open;
return s;
}
这意味着如果您希望继承该类,则只需要更改构造函数。
当然,如果您希望实现真正的多态,那么您不想更改任何代码。您可以通过将init函数作为参数传递给构造函数来解决此问题。
头文件:
typedef void init_func_t (void);
c file:
// constructor:
Serial* SerialCreate (init_func_t* init)
{
Serial* s = malloc(sizeof (*s));
...
init();
return s;
}
然后从继承类的init函数中设置所有私有成员函数。