【问题标题】:Static function overloading?静态函数重载?
【发布时间】:2012-06-28 06:55:13
【问题描述】:

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

  1. 定义接口的基类:因此我可以使用基类指针来访问函数。

  2. 出于内存管理目的(这是一个内存有限的嵌入式系统),我希望静态分配覆盖函数。我接受这样的结果,即使用静态函数,我如何操作函数中的数据会受到限制。

    我目前的想法是,我可以通过将其封装为实际上是静态的函数来保留轻重载函数。

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

【问题讨论】:

  • 当您说“静态”时,您的意思是“非虚拟”?当您说“重载”时,您的意思是覆盖吗?重载是同名但不同的参数,因此是不同的功能。覆盖是相同的参数,并且要求被覆盖的函数是虚拟的。
  • @MvG 我对区别很模糊。覆盖是我所追求的......我会编辑它。
  • @VanDarg:程序在嵌入式系统上运行的事实正在推动不消耗堆栈空间的愿望。我认为(但我以前错了,我是新手)声明函数静态应该可以将代码保持在闪存中。
  • "出于内存管理的目的...我希望静态分配重载函数。" 我认为您在这里有一个误解。代码是否存在于闪存中与方法是静态的还是非静态的无关。您可能想到局部变量,除非它们被声明为静态,否则它们确实会占用堆栈空间。
  • 好的,这是教育性的。因此,如果我理解正确,对于一个类成员函数的多个实例,通常不会将其作为实例的一部分进行复制,对吗?如果这是正确的,那么我不应该看到我的堆栈需求通过将函数设为静态来缩小?

标签: c++ embedded


【解决方案1】:

是否存在满足我列举的要求的面向对象的设计模式?

是的,普通的旧虚拟函数。您的愿望是“静态分配的压倒一切的功能”。虚函数静态分配的。也就是说,实现这些功能的代码存在一次,并且只有一次,并且在编译/链接时是固定的。根据您的链接器命令,它们很可能像任何其他函数一样存储在闪存中。

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\n";
  }
  virtual void undoit() {
    // yes, you got it.
    std::cout << "WORLD\n";
  }
};

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.
}

【讨论】:

    【解决方案2】:

    静态成员函数只是普通函数(如非成员函数),位于类的命名空间内。这意味着您可以将它们视为普通函数,以下解决方案应该这样做:

    class Interface
    {
      public:
        void (*function) ();
    };
    
    class Implementation: public Interface
    {
      public:
        Implementation()
        {
          function = impl_function;
        }
    
      private:
        static void impl_function() 
        {
          // do something
        }
    };
    

    然后

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

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

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

    【讨论】:

      【解决方案3】:

      出于内存管理目的(这是一个嵌入式系统 有限的内存)我希望覆盖函数是静态的 已分配。

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 2011-07-18
          • 2013-08-01
          • 2011-03-03
          • 2022-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多