1

As it's shown in the following code, I can call a non-static member function A::f without instantiating an object of the class. This is only possible when the function is not bound to any other member. For example, I cannot call A::g in a similar fashion.

It seems to me that the call to A::f as shown in the code below behaves like calling a static member function. Is such a conclusion correct? How can this behavior be justified?

#include <iostream>
using namespace std;

struct A {
    void f() { cout << "Hello World!"; }    
    void g() { cout << i; } 
    int i = 10;
};

int main() {
    auto fPtr = reinterpret_cast<void(*)()>(&A::f);
    (*fPtr)(); // OK

//  auto gPtr = reinterpret_cast<void(*)()>(&A::g); 
//  (*gPtr)(); // Error!
    return 0;
}
Eissa N.
  • 1,695
  • 11
  • 18
  • 2
    Related: [Calling class method through NULL class pointer](http://stackoverflow.com/questions/2505328/calling-class-method-through-null-class-pointer) – πάντα ῥεῖ Jun 01 '16 at 22:51
  • @πάνταῥεῖ That's even more interesting! – Eissa N. Jun 01 '16 at 22:56
  • It's merely the same regarding the outcome :-P ... – πάντα ῥεῖ Jun 01 '16 at 22:58
  • The cast should give a diagnostic – M.M Jun 01 '16 at 23:42
  • @M.M I was expecting an error when I faced it, but at least [some compilers](http://ideone.com/FokQed) don't complain. – Eissa N. Jun 01 '16 at 23:45
  • @EissaN. ideone suppresses a lot of error messages. Use an actual compiler – M.M Jun 01 '16 at 23:45
  • 1
    You should never rely on undefined behavior... On the other hand, an undefined behavior by the standard might not necessarily mean that the behavior is not defined by the compiler or platform (for example, COM virtual table format under Windows is well defined). Also the actual behavior in such case might depends on many factors like declaration modifiers or inheritance. – Phil1970 Jun 02 '16 at 00:16
  • @EissaN. Interestingly [related Q&A](http://stackoverflow.com/questions/37580179/getting-virtual-table-pointer-c) I also answered. – πάντα ῥεῖ Jun 02 '16 at 00:35
  • @EissaN. _"I was expecting an error when I faced it"_ No, not all compilers really warn you or issue an error message if you call UB. Especially not in conjunction with `reinterpret_cast<>()`. – πάντα ῥεῖ Jun 02 '16 at 00:37

1 Answers1

5

Is such a conclusion correct? How can this behavior be justified?

It's undefined behavior.

Pretty useless to ask for how it should specifically behave. Pick one or more from the list:

  • 2)Schroedingers cat is always found dead when you open the chest1
  • Your fridge explodes
  • You see the behavior you get
  • Little demons are flying out from your nostrils
  • 1)You get time warped back to the point, when you put the living cat into the chest2
  • ...
  • All of the above happens simultaneously

void f() { cout << "Hello World!"; }  

Well, the fact that your code doesn't rely on any member variable data makes it likely, that any decent implementation works without "crashing".

Though, it's simply UB to call a class member function without a valid class instance, as mentioned above.
So you can't predict what happens, or should rely on your observations.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    The fact that it could crash might depend on the calling convention as the incorrect cast might cause "this" to not be pushed on the stack but poped out anyway or it could maybe cause registers conflicts depending on what is assumed for a member call vs a free function call. – Phil1970 Jun 02 '16 at 00:23
  • @Phil1970 You're assuming the compiler does the "reasonable" thing in undefined behavior. – uh oh somebody needs a pupper Jun 02 '16 at 01:16
  • [Didn't we just discuss something like this a month ago?](http://stackoverflow.com/questions/36893251/why-does-the-enhanced-gcc-6-optimizer-break-practical-c-code) – T.C. Jun 02 '16 at 01:24