gpt4 book ai didi

c - 在不使用函数指针的情况下替代在 C 中引用虚拟表。

转载 作者:太空宇宙 更新时间:2023-11-04 04:58:50 26 4
gpt4 key购买 nike

我正在通过使用 Polymorphism (in C) 中描述的虚拟表来利用 C 中的多态性效果很好。

不幸的是,我当前项目的限制不允许我在我的代码的某些部分中使用函数指针或对结构的引用。因此,我不能直接使用原始方法。

在上述方法中,基“类/结构”有一个指向虚拟表的成员。为了驾驭这个指针,我决定用一个枚举代替它,作为访问虚拟表的键。

它有效,但我想知道这是否是最佳解决方案。你有没有比我的建议更合适的替代方案?

/**
* This example shows a common approach to achive polymorphism in C and an
* alternative that does NOT include a reference to function pointer in the
* base
* class.
**/
#include<stdio.h>

// some functions to make use of polymorphism
void funBase1()
{
printf("base 1 \n");
}
void funBase2()
{
printf("base 2 \n");
}
void funDerived1()
{
printf("derived 1 \n");
}
void funDerived2()
{
printf("derived 2 \n");
}


// struct to host virtual tables
typedef struct vtable {
void (*method1)(void);
void (*method2)(void);
}sVtable;

// enumerate to access the virtual table
typedef enum {BASE, DERIVED} eTypes;

// global virtual table used for the alternative solution
const sVtable g_vtableBaseAlternative[] = {
{funBase1, funBase2},
{funDerived1, funDerived2}, };


// original approach that i cannot use
typedef struct base {
const sVtable* vtable;
int baseAttribute;
}sBase;

// alternative approach
typedef struct baseAlternative {
const eTypes vtable_key;
int baseAttribute;
}sBaseAlternative;


typedef struct derived {
sBase base;
int derivedAttribute;
}sDerived;

// original way to use
static inline void method1(sBase* base)
{
base->vtable->method1();
}

const sVtable* getVtable(const int key, const sVtable* vTableDic)
{
return &vTableDic[key];
}

// Alternative to get a reference to the virtual table
static inline void method1Aternative(sBaseAlternative* baseAlternative)
{
const sVtable* vtable;
vtable = getVtable(baseAlternative->vtable_key, g_vtableBaseAlternative);
printf("alternative version: ");
vtable->method1();
}

int main() {

const sVtable vtableBase[] = { {funBase1, funBase2} };
const sVtable vtableDerived[] = { {funDerived1, funDerived2} };


sBase base = {vtableBase, 0 };
sBase derived = {vtableDerived, 1 };
sBaseAlternative baseAlternative = {DERIVED, 1 };

method1(&base);
method1(&derived);
method1Aternative(&baseAlternative);

}

最佳答案

my current project does not allow me to use function pointer or reference to structs

您可以使用 T 数组(您喜欢的任何类型)来表示数据类型。例如,我倾向于使用 unsigned char 的数组来序列化和反序列化我的数据结构以进行网络传输...例如,假设您正在使用 sprintfsscanf 用于序列化和反序列化(你不应该真的这样做,但它们对于演示来说没问题)...而不是 struct 参数,你使用 char * 参数,然后使用 sscanf 将该数据读取到局部变量,使用 sprintf 修改它...覆盖 不允许引用 struct 问题。

关于函数指针问题,您可以将所有函数组合成一个switch打开... a < em>字符串形式的标记结构...这是一个简单(但不完整)的示例,涉及的两个候选者:一个长度前缀字符串,它使用两个从 C 字符串行为和 C 字符串 编码长度和类型的字节。

enum { fubar_is_string, fubar_is_length_prefixed_string };
typedef unsigned char non_struct_str_class;

size_t non_struct_strlen(non_struct_str_class *fubar) {
size_t length = 0;
switch (fubar++[0]) {
case fubar_is_length_prefixed_string:
length = fubar++[0];
length <<= 8;
length += fubar++[0];
// carry through into the next case
// to support strings longer than 64KB
case fubar_is_string: if (!length)
length = strlen(fubar);
/* handle fubar as string */
}
return length;
}

C 是一种图灵完备的编程语言,因此它当然可以用来模仿面向对象的多态性...但它远好模仿过程多态性,或者在某些情况下甚至是函数式多态性...例如,您可以说qsortbsearch 使用原语类似于 map 的参数多态形式(甚至更类似于 filter 习语)。

您也可以使用 _Generic 并取得有限的成功,例如 the C11 standard does通过为所有标准浮点类型提供一个通用的cbrt宏:

#define cbrt(X) _Generic((X),                                      \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)

如果您要走模拟路线,预处理器特别有用...您可能对 Klemens 的 C11 书感兴趣。

关于c - 在不使用函数指针的情况下替代在 C 中引用虚拟表。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51667739/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com