C中的多态函数参数/返回值

时间:2012-07-09 15:08:03

标签: c polymorphism c89

我正在使用嵌入式微控制器,我必须将多种类型的数据读/写到非易失性RAM(NVRAM)。我想避免为每个值编写单独的读/写函数来存储在NVRAM中,如下所示:

void Write_Value1(int value);
int Read_Value1(void);
void Write_Value2(unsigned long value);
unsigned long Read_Value2(void);
...

随着读/写项目列表的增长,维护起来非常麻烦。有几种方法可以用C ++解决这个问题,例如模板。使用模板,我可以编写一个.Read().Write(T value)函数,每个要读/写的项都可以访问。无论如何从C获得这种行为?我怀疑有一些方法,使用void指针和vtable的一些组合。我想以更多态的方式处理这个问题,并且具有以类似的方式读取/写入每个项目到NVRAM的功能。

5 个答案:

答案 0 :(得分:10)

您可以[非常接近]使用宏来模拟C中的C ++模板。

至少有两种方法可以做到这一点。


第一种方法:“橡皮图章”宏

为函数定义声明/定义宏

#define DECLARE_READ_WRITE(suffix, type)\
  type Read_Value_##suffix(void);
  void Write_Value_##suffix(type val);

#define DEFINE_READ_WRITE(suffix, type)\
  type Read_Value_##suffix(void) {\
    /* your code */ \
  }\
  void Write_Value_##suffix(type val) {\
    /* your code */ \
  }

然后在一些头文件中执行

DECLARE_READ_WRITE(long, long)
DECLARE_READ_WRITE(int, int)

并在某些实施文件中

DEFINE_READ_WRITE(long, long)
DEFINE_READ_WRITE(int, int)

将“生成”Read_Value_intWrite_Value_intRead_value_longWrite_value_long的声明和定义。


第二种方法:参数化包含文件

创建两个头文件。一个用于声明(read_write.h.template

TYPE__ CONCAT(Read_Value_, SUFFIX__)(void);
void CONCAT(Write_Value_, SUFFIX__)(TYPE__ val);

和一个用于定义(read_write.c.template

TYPE__ CONCAT(Read_Value_, SUFFIX__)(void)
{
  /* your code */
}

void CONCAT(Write_Value_, SUFFIX__)(TYPE__ val)
{
  /* your code */
}

这里CONCAT是宏标记连接的通常实现(也可以/应该在第一种方法中使用)。

然后将“模板化”代码包含在适当的头文件和实现文件中

#define TYPE__ int
#define SUFFIX__ int
#include "read_write.h.template"
#undef TYPE__
#undef SUFFIX__

#define TYPE__ long
#define SUFFIX__ long
#include "read_write.h.template"
#undef TYPE__
#undef SUFFIX__

在带有read_write.c.template标题的某个实现文件中也是如此。

后一种方法具有产生可调试代码的额外好处。即您可以在调试器中单步执行它,就像它通常适用于C ++模板一样。

答案 1 :(得分:4)

你可以使用void指针和大小来做到这一点:

void write_value (void *data, size_t size);
void* read_value (size_t size);

然后:

write_value ( (void *) &int_val, sizeof (int));
write_value ( (void *) &ulong_val, sizeof (unsigned long));

intptr = read_value (sizeof (int));
charptr = read_value (sizeof (char));

read_value然后需要malloc某些东西并将其返回。当你宁愿读自动时,这有时可能只是开销。然后做:

/* Declaration.  */
void read_value (void *data, size_t size);

/* Use.  */
read_value (&automatic_var, sizeof (automatic_var));

最后,您可以在all sorts of ways中“模拟”模板。

答案 2 :(得分:3)

基于目标类型返回一个不同的类型(几乎?)不可能用C.你可以用宏来模仿它。例如:

#define WRITE(x)  write_value(x, sizeof(x))
#define READ(x)  read_value(&x, sizeof(x))

现在你可以编写write_value()和read_value()来根据长度复制数据,同时考虑内部例程中的字节顺序。

答案 3 :(得分:3)

C中没有这样的东西。但是,你可以使用结构方法。

#define T_VOID  0
#define T_INT   1
#define T_ULINT 2

typedef struct 
{
    int type;
    union 
    {            
        int a; 
        unsigned long b; 
    } my_union;
} my_struct;

void write_value(my_struct *s)
{
    switch (s->type) 
    {
        case T_VOID:
        // do something
        break;
        case T_INT: 
        // do something with s->my_union.a
        break;
        case T_ULINT: 
        // do something with s->my_union.b
        break;
    }
}

以同样的方式,read_value将返回my_struct指针。

答案 4 :(得分:2)

查看Posix readwrite函数,然后执行类似操作:

void read(int address, void * data, int size);
void write(int address, const void * data, int size);

然后:

read(address, &x, sizeof(x));
write(address, &x, sizeof(x));