-6
#include <iostream>
using namespace std;
class Person
{
public:
        void P(){ cout << "Person P" << endl; }
        virtual void Print(){ cout << "Person Print" << endl; }
        Person(){ cout << "Constructor Person" << endl; }
        virtual ~Person(){ cout << "Dectructor Person" << endl; }
};
class Developer : public Person
{
public:
        void Pi() { cout << "Developer Pi" << endl; }
        void Print() override
        {
                cout << "Developer Print" << endl;
        }
        Developer(){ cout << "Constructor Develoeper" << endl; }
        ~Developer(){ cout << "Dectructor Develoer" << endl; }
};
int main()
{
        Person *p = new Person();
        Developer* d = dynamic_cast<Developer*>(p);
        d->Pi();

        delete p;
        delete d;
   return 0;
}

Output:

Constructor Person
Developer Pi
Dectructor Person

Why can I invoke Developer's function Pi?

How can invoke Pi without Developer's Constructor?

Note that Pi is only declared in class Developer.

nobody
  • 19,814
  • 17
  • 56
  • 77

4 Answers4

3

You cannot. Your code has an undefined behavior. If I modify the main() function to:

int main()
{
    Person *p = new Person();
    Developer* d = dynamic_cast<Developer*>(p);
    assert(d!=0);
    d->Pi();

    delete p;
    delete d;
    return 0;
}

Then the assertion d!=0 is triggered. That shows that the dynamic_cast failed. You call Developer::Pi on a null pointer, and using your compiler it happens to run fine, probably because Developer::Pi does not use this.

lrineau
  • 6,036
  • 3
  • 34
  • 47
  • 1
    @irineau, this is not OP's answer. without `assert` the code works and surprisingly calls `Pi`, the question is why – Rakib May 19 '14 at 15:10
2

with Developer* d = dynamic_cast<Developer*>(p);
you have d == nullptr.

with d->Pi(); You invoke undefined behavior:

method are generally equivalent to a function which take extra this as parameter and as you don't use this the method seems to work in your case.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

It is becuase of dynamic_cast. You are not referring to any variables in the instance, therefor it does not fail.

Accessing any of the virtual methods or accessing anything that would be stored in the object would give access violation.

NeutronCode
  • 365
  • 2
  • 13
0

by stating that d is a pointer to an object of the Developer class you give a hint to the compiler. You also declared void Pi() not to be virtual, therefore the compiler used early binding ( compile time ). That means that the address of the function that is invoked is pinned during compilation, and doesn't need an object to be evaluated ( unlike virtual methods )

When calling d->Pi(), it is the same as you'd call Pi(d) with Pi taking a pointer to a Developer instance. In MFC there is a method called Validate or something like that which uses the very same mechanism to check if your pointer isn't null :)

You don't get a crash on delete d because it is in the standard, that deleting a null pointer is OK, and does nothing ( deleting a dirty pointer is undefined tough ).

Just add the word virtual to the Pi method signature OR add a field to Developer class and try to moddify that field in the Pi method. You will then see the difference ;)

user2511124
  • 158
  • 5