C 语言 虚函数与非虚函数

一、虚函数


struct Foo;
typedef struct FooVtb1{
    void (* const func0)(struct Foo * pThis);
    void (* const func1)(struct Foo * pThis);
    void (* const func2)(struct Foo * pThis);
} FooVtb1;
    
static FooVtb1 foo_vtb1 = {func0_impl,func1_impl,func2_impl};
typedef struct Foo{
    const int count;
    const FooVtb1 * const pTtv1;
}Foo;
   
    Foo foo0 = {0,&foo_vtb1};
    Foo foo1 = {1,&foo_vtb1};
    Foo foo2 = {2,&foo_vtb1};

二、非虚函数


typedef struct Foo{
    int count;
    void (* const func0)(struct Foo * pThis);
    void (* const func1)(struct Foo * pThis);
    void (* const func2)(struct Foo * pThis);
} Foo;
假设这里需要增加一个将count复位为0的函数,这时增加一个虚函数倒也可以:


typedef struct Foo{
    int count;
    void (* const func0)(struct Foo * pThis);
    void (* const func1)(struct Foo * pThis);
    void (* const func2)(struct Foo * pThis);
    void (* reset_counter)(struct Foo * pThis);
 } Foo;
假如知识将count恢复为0,就没有必要动态地根据对象不同改变函数行为了。这种情况下,也可以单独使用一个函数来实现。


 void reset_foo_counter(struct Foo * pThis)
 {
     pThis->count = 0;
 }

这里由于没有使用函数指针,所以能够节省内存,但另一方面,也就意味着无法根据对象来动态地改变行为了。此外如果是C语言的话还有一个命名空间问题。函数命名为reset_foo_counter表明该函数是Foo使用的函数,如果简单地以

reset_counter命名的话,碰巧Bar结构体也有一个名为count的成员和一个复位函数reset_counter,则会冲突。

如果结构体内持有函数指针,就不用考虑这个问题了。结构体Foo中的reset_counter和结构体Bar中的reset_counter 会被当作不同的函数处理。在函数名前加上一个static修饰符可以避免命名冲突。此外,相比非虚函数,使用函数指针的方式更加容易测试。

那么什么时候应该使用非虚函数,什么时候应该使用函数指针呢?这是很难回答的问题。一般来说,经验欠缺的人很容易过度使用非虚函数。一般情况下,优先使用函数指针,只有在内存非常有限,对象行为不会变化的情况下,或者是非常有把握的情况下才考虑使用非虚函数。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值