7

I'll start by saying I understand that that only nonstatic member functions can be virtual, but this is what I want:

  1. A base class defining an interface: so I can use base class pointers to access functions.

  2. For memory management purposes (this is an embedded system with limited ram) I want the overriding functions to be statically allocated. I accept the consequence that with a static function, there will be constraints on how I can manipulate data in the function.

    My current thinking is that I may keep a light overloading function by making it a wrapper for a function that actually is static.

Please forbear telling me I need to re-think my design. This is why I am asking the question. If you'd like to tell me I'm better off using c and using callbacks, please direct me to some reading material to explain the pitfalls of using an object oriented approach. Is there a object oriented pattern of design which meets the requirements I have enumerated?

Community
  • 1
  • 1
2NinerRomeo
  • 2,687
  • 4
  • 29
  • 35
  • 2
    When you say “static”, so you mean “non-virtual”? When you say “overloading”, do you rather mean overriding? Overloading is same name but different arguments, thus a different function. Overriding is same arguments, and requires the overridden function to be virtual. – MvG Jun 26 '12 at 21:27
  • @MvG I was hazy on the distinction. Overriding is what I am after..I'll edit that. – 2NinerRomeo Jun 26 '12 at 21:43
  • @VanDarg: The fact that the program is being run on an embedded system is driving the desire to not consume stack space. I think (but I've been wrong before and I'm new at this) Declaring the function static should make it possible to keep the code in flash. – 2NinerRomeo Jun 26 '12 at 21:43
  • 2
    "*For memory management purposes ... I want the overloading functions to be statically allocated.*" I think you have a misunderstanding here. Whether the code lives in flash is irrespective of whether the method is static or non-static. You *may* be thinking of local variables, which do consume stack space unless they are declared static. – Robᵩ Jun 26 '12 at 21:44
  • Allright, this is educational here. So If I understand correctly, For multiple instances of a class member functions are generally NOT copied as part of the instance, correct? If that's right, then I should not see my stack requirements shrink by making functions static? – 2NinerRomeo Jun 26 '12 at 22:44
  • Sounds like [Curiously Recurring Template Pattern](https://stackoverflow.com/q/4173254/608639). Possible duplicate of [Alternative to c++ static virtual methods](https://stackoverflow.com/questions/2721846/alternative-to-c-static-virtual-methods) – jww Jun 11 '17 at 16:09

4 Answers4

7

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

Yes, plain old virtual functions. Your desire is "the overriding functions to be statically allocated." Virtual functions are statically allocated. That is, the code which implements the functions exists once, and only once, and is fixed at compile/link time. Depending upon your linker command, they are as likely to be stored in flash as any other function.

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.
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
4

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

All functions in C++ are always statically allocated. The only exception is if you manually download and utilize a JIT.

Puppy
  • 144,682
  • 38
  • 256
  • 465
3

Static member functions are just plain functions (like non-member functions), that are inside the namespace of the class. That means you can treat them like plain functions, and the following solution should do:

class Interface
{
  public:
    void (*function) ();
};

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

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

then

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

The problem with this approach is that you would be doing almost what the compiler does for you when you use virtual member functions, just better (needs less code, is less error-prone, and the pointer to the implementation functions are shared). The main difference is that using virtual your function would receive the (invisible) this parameter when called, and you would be able to access the member variables.

Thus, I would recommend to you to simply not do this, and use ordinary virtual methods.

lvella
  • 12,754
  • 11
  • 54
  • 106
0

The overhead with virtual functions is two-fold: besides the code for the actual implementations (which resides in the code segment, just like any other function you write), there is the virtual function table, and there are pointers to that table. The virtual function table is present once for each derived class, and its size depends on the number of virtual functions. Every object must carry a pointer to its virtual function table.

My point is, the per-object overhead of virtual functions is the same no matter how many virtual functions you have, or how much code they contain. So the way you arrange your virtual functions should have little impact on your memory consumtion, once you have decided that you want some degree of polymorphism.

MvG
  • 57,380
  • 22
  • 148
  • 276