zoukankan      html  css  js  c++  java
  • [C]虚函数、虚函数表、非虚函数

    虚函数、虚函数表

    使用结构体表示对象,状态通过属性表示,行为通过函数指针表示。

    如果对象的行为都一致,每个对象都会初始化它的函数指针,这样会导致内存浪费。

    看下面这个例子:

     1 typedef struct Foo {
     2     int count;   
     3     void (* const func0)(struct Foo *pThis);
     4     void (* const func1)(struct Foo *pThis);
     5     void (* const func2)(struct Foo *pThis);
     6 } Foo;
     7 // 根据对象定义生成几个对象
     8 Foo foo0 = {0, func0_impl, func1_impl, func2_impl};
     9 Foo foo1 = {1, func0_impl, func1_impl, func2_impl};
    10 Foo foo2 = {2, func0_impl, func1_impl, func2_impl};

    出现以下情况会导致浪费内存

    • 有多个对象都具有相同的行为
    • 有较多的函数指针
    • 需要生成较多数量的对象

    虚函数:通过函数指针实现,根据对象初始化不同而展现不同功能。

    虚函数表:虚函数的集合,如下所示:

    typedef struct FooVtbl {
        void (* const func0)(struct Foo *pThis);
        void (* const func1)(struct Foo *pThis);
        void (* const func2)(struct Foo *pThis);
    } FooVtbl;
    
    typedef struct Foo {
        const int count;
        const FooVtbl * const pVtbl;
    } Foo;
    
    int main()
    {
        static FooVtbl foo_vtbl = {func0_impl, func1_impl, func2_impl};
    
        Foo foo0 = {0, &foo_vtbl};
        Foo foo1 = {1, &foo_vtbl};
        Foo foo2 = {2, &foo_vtbl};
    
        foo0.pVtbl->func0(&foo0);
    
        return EXIT_SUCCESS;
    }

    这就是虚函数表减少内存浪费的方式,优缺点如下:

    1. 代码结构中,仅需要对象持有指向虚函数表的指针即可,无需持有函数指针,可节约内存。
    2. 由于调用会经过虚函数表,程序的结构变复杂了。

     非虚函数

    对象内持有的函数指针为虚函数,它可以根据对象的不同而使其行为发生变化。但如果函数在不同对象中的行为是相同的,对象中就无需持有函数指针了。例如

    typedef struct FooVtbl {
        void (* const func0)(struct Foo *pThis);
        void (* const func1)(struct Foo *pThis);
        void (* const func2)(struct Foo *pThis);
    } FooVtbl;
    
    typedef struct Foo {
        const int count;
        FooVtbl *pVtbl;
        void (*reset_counter)(struct Foo *pThis);
    } Foo;

    优点

    1. 节省内存。

    缺点

    1. 无法根据对象动态的改变其行为。
    2. 命名空间问题。

    建议:优先使用函数指针,只有在内存有限、对象行为不会变化的情况下等,才考虑使用非虚函数。

  • 相关阅读:
    win7 安装 redis +php扩展
    HTTP Status 500
    浅谈java8新特性之stream
    关于排序算法中的稳定与不稳定
    关于面试中的mysql试题1
    mysql关于case-when-end的使用
    eclipse项目启动报:Project facet Java version 1.8 is not supported
    mysql 5.7密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
    浅谈并行与并发
    浅谈Java垃圾回收(GC)
  • 原文地址:https://www.cnblogs.com/yanxin880526/p/15087640.html
Copyright © 2011-2022 走看看