21

C++ 语言提供virtual函数。在纯 C 语言实现的约束下,怎样才能达到类似的效果呢?

4

4 回答 4

33

从这里偷来的。

来自 C++ 类

class A {
protected:
    int a;
public:
    A() {a = 10;}
    virtual void update() {a++;}
    int access() {update(); return a;}
};

可以导出 C 代码片段。的三个 C++ 成员函数class A使用离线(独立)代码重写,并按地址收集到名为A_functable. 函数表的数据成员A并与函数表组合成一个名为A.

struct A;

typedef struct {
    void (*A)(struct A*);
    void (*update)(struct A*);
    int (*access)(struct A*);
} A_functable;

typedef struct A{
    int a;
    A_functable *vmt;
} A;

void A_A(A *this);
void A_update(A* this);
int A_access(A* this);

A_functable A_vmt = {A_A, A_update, A_access};

void A_A(A *this) {this->vmt = &A_vmt; this->a = 10;}
void A_update(A* this) {this->a++;}
int A_access(A* this) {this->vmt->update(this); return this->a;}

/*
class B: public A {
public:
    void update() {a--;}
};
*/

struct B;

typedef struct {
    void (*B)(struct B*);
    void (*update)(struct B*);
    int (*access)(struct A*);
} B_functable;

typedef struct B {
    A inherited;
} B;

void B_B(B *this);
void B_update(B* this);

B_functable B_vmt = {B_B, B_update, A_access};

void B_B(B *this) {A_A(this); this->inherited.vmt = &B_vmt; }
void B_update(B* this) {this->inherited.a--;}
int B_access(B* this) {this->inherited.vmt->update(this); return this->inherited.a;}

int main() {
    A x;
    B y;
    A_A(&x);
    B_B(&y);
    printf("%d\n", x.vmt->access(&x));
    printf("%d\n", y.inherited.vmt->access(&y));
}

比必要的更复杂,但它明白了重点。

于 2010-06-24T20:27:00.293 回答
1

@GCC ....一个虚函数在对象的基类中声明,然后在子类中“覆盖”或实现。即,假设您有 Vehicle Base 类,并且您创建了两个子类,Motorcycle 和 Automobile。基类会声明一个 AddTires() 的虚函数,然后子类会实现这个函数,每个子类会以不同的方式实现它。汽车有 4 个轮子,而摩托车有 2 个轮子。不过,我无法为您提供 C 或 C++ 的语法。希望这可以帮助

于 2010-06-24T20:28:45.760 回答
0

这里是什么是虚函数的描述。

没有办法在纯 C 中实现虚函数,因为 C 没有继承的概念。

更新: 正如下面评论中所讨论的,可以使用结构和函数指针在纯 C 中做类似于虚函数的事情。但是,如果您习惯于像 C++ 这样具有“真正的”虚函数的语言,您可能会发现 C 近似值远不那么优雅且更难使用。

于 2010-06-24T20:22:22.833 回答
0

虚函数是 C++ 面向对象的一个​​特性。它们指的是依赖于特定对象实例的方法,而不是您当前携带它们的类型。

换句话说:如果您将一个对象实例化为 Bar,然后将其转换为 Foo,则虚拟方法仍将是它们在实例化时的方法(在 Bar 中定义),而其他方法将是来自 Foo 的方法。

虚函数通常是通过 vtables 实现的(这让你可以做更多的研究;))。

您可以通过将结构用作穷人的对象并在其中保存函数指针来在 C 中模拟类似的事情。

(更准确地说,非虚函数使得该方法应该取自哪个类变得模棱两可,但实际上我相信 C++ 使用当前类型。)

于 2010-06-24T20:26:43.617 回答