Sanjay
Sanjay

Reputation: 17

C++ Concepts Acessing public methods

#include <iostream>

class Test {
public:
    int i;
    void print()
    {
        std::cout << "Hello" << std::endl;
    }
};

int main()
{
    class Test *p = NULL;
    p->print();
    (*p).print();
}

Output:

Hello
Hello

I understand that objects methods and members variables are stored in different location in memory but when p is assigned as NULL how it can resolve to invoke Test::print()

Test6:~ 1001> g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Test6:~ 1002> g++ manoj.cpp
Test6:~ 1003> ./a.out
Hello
Hello
Test6:~ 1004> cat manoj.cpp
#include <iostream>

class Test {
public:
int i;
void print()
{
std::cout << "Hello" << std::endl;
}
};

int main()
{
class Test *p = NULL;
p->print();
(*p).print();
}
Test6:~ 1005>

Upvotes: 0

Views: 209

Answers (3)

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20730

What you did is not a "good developed piece of code", but it works, because, even if the this pointer is null, you never (either explicitly or implicitly) dereferenced it.

your *p (or p->) is of class Test, and Test::print doesn't refer to anything inside Test, so ... since a null Test is always a Test and you don't care about its content, the code compile and works.

But this code will run into trouble if:

  • Test::print is made to be virtual: in this case p->print() (or (*p).print()) have to go through the v-table of the actual object to detect which function to call. (*p can be whatever Test-derived), but since there is no object, no v-table can be detected, and the program will crash.
  • Test is made to have a member, and your print function made to print it: in this case, since p points to an invalid memory block, your function -wile accessing the member variable- will try to implicitly dereference a null this pointer to calculate where the member is. And will result in an invalid memory address, thus causing a crash.

In fact you just entered in that gray area called "undefined behavior": the language lawyers (the ones who wrote the specs) din't say anything about it (in particular: the never said "it is a (runtime) error to dereference an invalid pointer": they said "dereferencing an invalid pointer result in undefined behaviour" that barely means "we don't want tell you what should happen").

But since a compiler writer have to do something (the compiler cannot be "undefined"), since at compile time -while translating a line of code- they cannot know what the value of a pointer will be, they decided to translate the code any way.

And since the execution of the code doesn't break any process boundary, it doesn't crash. And since no "in process uninitialized space" is accessed, not messy values are seen and everything looks ok.

Welcome to the unmanaged languages word!

Upvotes: 0

Zeenobit
Zeenobit

Reputation: 5194

You simply cannot do this. This code wouldn't compile, and you cannot address a null pointer. Try using:

int main()
{
    // no need for 'class' keyword when declaring the pointer:
    Test* p = new Test(); // use default constructor provided by compiler
    p->print();
    (*p).print();
    // you also need to delete the pointer before returning, but that's irrelevant
    return 0; // you need this too
}

Upvotes: 0

JosephH
JosephH

Reputation: 8815

Unless a class has virtual functions(i.e. compiler does not create vtable), all the pointers to the methods will be hardcoded in the program, thus not requiring any of the variable information. However, even in that case, it would not have a valid this pointer, so it will still crash.

Upvotes: 3

Related Questions