0
#include <iostream>
using namespace std;

class A{
  private : static A *ob;
  public : static A* fun1();

  public : void show(string str){
     cout<<"This is :- "<<str<<endl;
  }
};

A* A::ob=NULL;

A* A::fun1(){
  if(ob==NULL){
     ob=new A();
     return ob;
  }
  return NULL;
}


int main() {
   A *ob1 = A::fun1();
   A *ob2 = A::fun1();

   ob1->show("A");    // line 1

   ob2->show("B");   //line 2

   return 0;
}

the output is :-

This is :- A
This is :- B

Although i expected only "This is :- A" since 'ob2' is NULL and dereferencing it should give error.

Can someone explain the output?

O'Neil
  • 3,790
  • 4
  • 16
  • 30
Ruosh
  • 31
  • 3
  • @Fureeish If i replace line1 and line 2 by `if(ob1!=NULL) ob1->show("A"); // line 1 if (ob2!=NULL) ob2->show("B"); //line 2 ` then why i get expected output, since ob2 in not NULL ? – Ruosh Sep 15 '18 at 22:42
  • This looks like an attempt of implementing singleton, except `A::fun()` should always return `ob` and never `NULL`. The idea is that if `ob` is `NULL` it will instance `ob` so it stops being `NULL`, and if `ob` is already instanced then it will just return it. – Havenard Sep 15 '18 at 22:45
  • Its very similar to singleton but what i tried to implement is that if an object of a class is already created then on creating another object it should report error ! – Ruosh Sep 15 '18 at 22:50
  • Well that's not reporting anything, maybe you should use `throw std::runtime_error("object already exists");` or something like that. – Havenard Sep 15 '18 at 22:53
  • Also see https://stackoverflow.com/questions/47026061/whats-the-difference-between-how-virtual-and-non-virtual-member-functions-are-c – ADG Sep 16 '18 at 11:09

1 Answers1

3

Dereferencing NULL is undefined behaviour (Why dereferencing a null pointer is undefined behaviour?), and so is invoking a non-static member function through NULL: When does invoking a member function on a null instance result in undefined behavior?

That means you can’t rely on any behaviour, not even a crash. On many platforms this will crash, but your described output is just as valid.

Pascal Kesseli
  • 1,620
  • 1
  • 21
  • 37
  • 3
    @Fureeish Yes, there is. – melpomene Sep 15 '18 at 22:32
  • fun1 returns NULL if the static ob member is not NULL, no? – Pascal Kesseli Sep 15 '18 at 22:33
  • 2
    @melpomene, no there is not. the this ptr is never dereferenced in this code. – ADG Sep 15 '18 at 22:35
  • 1
    @AndrewDGrant Did you look at the implementation of `fun1`? During first call of it, it returns a valid pointer, while in all subsequent calls it returns `NULL`. Even original asker acknowledges this, and only asks about why doesn't it crash/give error. – Algirdas Preidžius Sep 15 '18 at 22:37
  • 3
    Still undefined behaviour though: https://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-beha – Pascal Kesseli Sep 15 '18 at 22:38
  • @Algirdas, please see my answer. There is no dereferencing of a null pointer in this code. – ADG Sep 15 '18 at 22:41
  • @AndrewDGrant Please read the question, that was linked to you: https://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-beha More specifically this quote from standard: "_If `E1` has the type “pointer to class X,” then the expression `E1->E2` is converted to the equivalent form `(*(E1)).E2;`_" Hence, the dereference is there. If it works for you, and there is an explanation for such behavior, it doesn't mean that the behavior is defined. – Algirdas Preidžius Sep 15 '18 at 22:44
  • Please see http://www.cs.technion.ac.il/users/yechiel/c++-faq/dyn-binding.html. Specifically "the compiler resolves non-virtual functions exclusively at compile-time based on the type of the pointer." – ADG Sep 16 '18 at 11:08