How/why does this work?

B

beerbal

Hello,

I am a bit confused as to how the following snippet would work?

#include <iostream>

class Foo
{
public:
void doSomething()
{
std::cout << "Foo::doSomething()\n";
}
};


int main()
{
Foo* ptr;
ptr->doSomething();

return 0;
}

I compiled this with both g++ and VC and in both cases, program printed
Foo::doSomething() when run.

My question is, since ptr is declared as just a pointer to class Foo,
how/why does the call to doSomething() go thru' even when there is no
object created explicitly?

Thanks,
Beerbal
 
M

mlimber

beerbal said:
Hello,

I am a bit confused as to how the following snippet would work?

#include <iostream>

class Foo
{
public:
void doSomething()
{
std::cout << "Foo::doSomething()\n";
}
};


int main()
{
Foo* ptr;
ptr->doSomething();

return 0;
}

I compiled this with both g++ and VC and in both cases, program printed
Foo::doSomething() when run.

My question is, since ptr is declared as just a pointer to class Foo,
how/why does the call to doSomething() go thru' even when there is no
object created explicitly?

Thanks,
Beerbal

You just got lucky.

Your call to Foo::doSomething is effectively translated into this:

_Foo_doSomething( ptr );

And the function itself becomes something like:

void _Foo_doSomething( Foo* this )
{
std::cout << "Foo::doSomething()\n";
}

Notice that you didn't use the implicit [this] pointer in the function.
If you had, the result would have been undefined behavior since it
doesn't point to a Foo object. Since the function doesn't use any data
members of Foo, it should actually be declared static, which would mean
that the implicit [this] pointer would be dropped from the call.

Cheers! --M
 
H

Henryk

Because you do not use any internal member variable in your
doSomething.

Actually you could declare your function as

static void doSomething() and then call Foo::doSomething() without even
definining a pointer to Foo.

All instances of a class share the same function. The function exists
in your executable. What changes is the "this" pointer that is passed
with your function call. It is unique for every object.
 
M

Marcus Kwok

beerbal said:
Hello,

I am a bit confused as to how the following snippet would work?

#include <iostream>

class Foo
{
public:
void doSomething()
{
std::cout << "Foo::doSomething()\n";
}
};


int main()
{
Foo* ptr;
ptr->doSomething();

return 0;
}

I compiled this with both g++ and VC and in both cases, program printed
Foo::doSomething() when run.

My question is, since ptr is declared as just a pointer to class Foo,
how/why does the call to doSomething() go thru' even when there is no
object created explicitly?

Since ptr is uninitialized, this is UB, thus the program can do
anything.

My guess is this: Since member functions behave essentially like
regular functions with a hidden "this" parameter, and since Foo has no
member variables, doSomething() is treated as a regular function call,
with the hidden "this" parameter set to uninitialized garbage. I
suspect that if you were to add a member variable to Foo, and try to use
this variable in doSomething(), then you might get a crash (but remember
all this is still UB).
 
V

Victor Bazarov

beerbal said:
I am a bit confused as to how the following snippet would work?

It has undefined behaviour. So, if it happens to behave the same
way you expect it to behave, it's a pure coincidence from C++ point
of view.
#include <iostream>

class Foo
{
public:
void doSomething()
{
std::cout << "Foo::doSomething()\n";
}
};


int main()
{
Foo* ptr;
ptr->doSomething();

return 0;
}

I compiled this with both g++ and VC and in both cases, program printed
Foo::doSomething() when run.
So?

My question is, since ptr is declared as just a pointer to class Foo,
how/why does the call to doSomething() go thru' even when there is no
object created explicitly?

That cannot be answered in terms of standard C++ language, except that
since you don't initialise 'ptr' it can _randomly_ point to some area in
memory that can be treated as a "valid object".

There are systems out there on which your program will abnormally end.

V
 
B

Ben Pope

beerbal said:
Hello,

I am a bit confused as to how the following snippet would work?

#include <iostream>

class Foo
{
public:
void doSomething()
{
std::cout << "Foo::doSomething()\n";
}
};


int main()
{
Foo* ptr;
ptr->doSomething();

return 0;
}

I compiled this with both g++ and VC and in both cases, program printed
Foo::doSomething() when run.

My question is, since ptr is declared as just a pointer to class Foo,
how/why does the call to doSomething() go thru' even when there is no
object created explicitly?

Dereferencing an uninitialised pointer is undefined behaviour. That
means it might do what you expect, it might do nothing, or it might
delete all the files on your hard drive.

It's pointless to speculate further, but here goes:

Foo::doSomething could be rewritten in C, as such:
doSomething(Foo& f);

Where Foo is just a struct.

Since Foo contains no data, and doSomething() doesn't rely on any data
of Foo, the argument is "optimised" away by the compiler and run as if
it were a standalone function.

Therefore there is no crash.

The behaviour is undefined, and it may or may not, be different
tomorrow... you should not rely on it.

Ben Pope
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,886
Members
47,419
Latest member
ArturoBres

Latest Threads

Top