关于C++:静态函数重载?

Static function overloading?

我首先要说的是,我理解只有非静态成员函数可以是虚拟的,但这正是我想要的:

  • 定义接口的基类:所以我可以使用基类指针访问函数。
  • 为了内存管理的目的(这是一个内存有限的嵌入式系统),我希望以静态方式分配覆盖函数。我接受这样的结果:对于一个静态函数,对于如何操作函数中的数据会有限制。

    我目前的想法是,通过使一个轻重载函数成为一个实际上是静态函数的包装器,我可以保留它。

  • 请不要告诉我我需要重新考虑我的设计。这就是我问这个问题的原因。如果你想告诉我我最好使用C和回调,请指导我阅读一些材料来解释使用面向对象方法的缺陷。是否有一个面向对象的设计模式满足我列举的需求?


    Is there a object oriented pattern of design which meets the requirements I have enumerated?

    是的,简单的旧虚拟函数。您希望"静态分配覆盖函数"。静态分配虚拟函数。也就是说,实现函数的代码只存在一次,而且只存在一次,并且在编译/链接时是固定的。根据您的链接器命令,它们可能与任何其他功能一样存储在闪存中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    class I {
      public:
      virtual void doit() = 0;
      virtual void undoit() = 0;
    };

    class A : public I {
      public:
      virtual void doit () {
        // The code for this function is created statically and stored in the code segment
        std::cout <<"hello,";
      }
      virtual void undoit () {
        // ditto for this one
        std::cout <<"HELLO,";
      }
    };

    class B : public I {
      public:
      int i;
      virtual void doit() {
        // ditto for this one
        std::cout <<"world
    "
    ;
      }
      virtual void undoit() {
        // yes, you got it.
        std::cout <<"WORLD
    "
    ;
      }
    };

    int main () {
       B b; // So, what is stored inside b?
            // There are sizeof(int) bytes for"i",
            // There are probably sizeof(void*) bytes for the vtable pointer.
            // Note that the vtable pointer doesn't change size, regardless of how
            // many virtual methods there are.
            // sizeof(b) is probably 8 bytes or so.
    }

    For memory management purposes (this is an embedded system with
    limited ram) I want the overriding functions to be statically
    allocated.

    C++中的所有函数都是静态分配的。唯一的例外是手动下载并使用JIT。


    静态成员函数只是类命名空间内的普通函数(如非成员函数)。这意味着您可以像处理普通函数一样处理它们,并且应该使用以下解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Interface
    {
      public:
        void (*function) ();
    };

    class Implementation: public Interface
    {
      public:
        Implementation()
        {
          function = impl_function;
        }

      private:
        static void impl_function()
        {
          // do something
        }
    };

    然后

    1
    2
    3
    Implementation a;
    Interface* b = &a;
    b->function(); // will do something...

    这种方法的问题在于,当您使用虚拟成员函数时,您将几乎像编译器为您做的那样做,只是做得更好(需要更少的代码,不易出错,并且实现函数的指针是共享的)。主要的区别是,使用virtual函数在调用时将接收(不可见的)this参数,并且可以访问成员变量。

    因此,我建议您不要这样做,使用普通的虚拟方法。


    虚拟函数的开销是双重的:除了实际实现的代码(与您编写的任何其他函数一样,它驻留在代码段中)之外,还有虚拟函数表,并且有指向该表的指针。对于每个派生类,虚函数表只存在一次,其大小取决于虚函数的数量。每个对象都必须携带指向其虚拟函数表的指针。

    我的观点是,无论您拥有多少虚拟函数,或者它们包含多少代码,虚拟函数的每个对象开销都是相同的。因此,一旦您决定需要某种程度的多态性,您安排虚拟函数的方式应该不会对内存消耗产生什么影响。