-2

Guys plz check the code below:

class Human
{ 
public:
    void chat(Human h)
    {
        cout << "human";
    }

    void chat(ComputerScientist c)
    {
        cout << "computer";
    }
};

class ComputerScientist : public Human
{
};

//Main function below
int main()
{
    Human* p, p1;
    //Uninitialized pointer above;

    p->chat(p1); //It shows perfectly the result without ANY error!
}

However, things go tricky if I make a function in derived class ComputerScientist which overrides the Human's one.

class Human
{
public:
    virtual void chat(Human* h)
    {
        cout << "about the weather";
    }

    virtual void chat(ComputerScientist* c)
    {
        cout << "about their own computer illiteracy";
    }
};

class ComputerScientist : public Human
{
public:
    virtual void chat(Human* h)
    {
        cout << " about computer games";
    }

    virtual void chat(ComputerScientist* c)
    {
        cout << " about others’ computer     illiteracy";
    }
};

And I use the same main function, it appears to be a segmentation fault in the null pointer line. But why?

Things have make change in two places in the second example:

  1. I used the overriding function by making it virtual.
  2. The function is taking a pointer as argument.
Deanie
  • 2,316
  • 2
  • 19
  • 35
Ftube
  • 13
  • 1
  • 3
    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off. " --- by someone – user3528438 Apr 22 '15 at 20:05
  • 1
    Related: http://stackoverflow.com/a/29151144/332733 – Mgetz Apr 22 '15 at 20:07
  • Also note that in `human* p, p1;` only `p` is a pointer. If you want both to be pointers then use `human *p, *p1;` – rpsml Apr 22 '15 at 20:19
  • 1
    The "C makes it easy to shoot yourself in the foot" quote is at http://stroustrup.com/bs_faq.html#really-say-that . – Max Lybbert Apr 22 '15 at 20:34

2 Answers2

4

The code you've written exhibits undefined behavior. Code that is experiencing undefined behavior may:

  • segmentation fault
  • output weird characters to the screen.
  • vary over different optimization levels and compilers
  • work exactly as you wanted it to.
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
3

In first case, your class is a POD (plain old data) and your chat function does not dereference/access any member variable- thus it appears to work okay (this is a bad practice though- due to undefined behavior). In case of virtual functions each object has vtable, which needs a valid pointer to work- thus leads to fault.

Here is how you can make your first case fault as well:

class Human 
{ 
    private:
        int n;
    public:

    void chat(Human h) 
    {
        cout << "human #" << n << endl;
    }

    void chat(ComputerScientist c) 
    {
        cout << "computer";
    }
};

class ComputerScientist:public Human{};

int main()
{
    Human* p,p1;
    //Uninitialized pointer above;
    p->chat(p1);//It shows perfectly the result without ANY error!

    return 0;
}
Sarang
  • 1,867
  • 1
  • 16
  • 31
  • 1
    Note: `thus it works okay.` Yes, this is why it works in this case, but this doesn´t mean it´s correct. What OP´s doing is to call a function which doesn´t depend in any way on p or p1, so the compiler generates a function call without being interested in these variables at all. But it doesn´t have to. It may crash (or anything else) – deviantfan Apr 22 '15 at 20:08
  • 1
    Just to be clear here `it works ok` should really read `it happens to work ok this time, it may not next time`. Undefined behaviour is a fickle thing and should really be avoided. – Mike Vine Apr 22 '15 at 20:09
  • @deviantfan: yes this kind of behavior is not okay- my answer is more towards why there was no seg fault. About coding this is not how it should be coded and should be flagged in code reviews – Sarang Apr 22 '15 at 20:10
  • @Sarang Don´t worry, I know what you meant. My comment was more for the OP and other readers. – deviantfan Apr 22 '15 at 20:12
  • @MikeVine: thanks- i have made the edits to text – Sarang Apr 22 '15 at 20:12
  • Brilliant answer pointing to the vtable. – Ftube Apr 22 '15 at 23:30
  • So is that equivalent to say I can treat the any class with virtual method as a 'hidden member variable(which is an array, vtable) embedded', therefore any wild pointer that access to the virtual member contained class would cause exception? (Simply to say any virtual class are implicitly NOT POD.)@Sarang – Ftube Apr 22 '15 at 23:33
  • Yes, see http://stackoverflow.com/questions/146452/what-are-pod-types-in-c for details about pod types – Sarang Apr 22 '15 at 23:49