problem with inheritance and virtual function

M

maadhuu

The following is a piece of code and the output of the code is pasted after
it . I dont understand how it works (while giving the output) .Can someone
enlighten me on this ?

thanking you .
maadhuu .
the following is the code

class base
{
int data;
public :
base() { }
virtual void virt()
{
}
};
class derived:public base
{
int data;
public :
derived(int a):data(a) { }
virtual void virt()
{
std::cout << data ;
}
};


int main()
{
int a = 1;
base *b[3] ;
for(int i = 0; i<3;++i)
{ b = &derived(a++);b->virt();
}
for(int i = 0; i<3;++i)
b->virt();
return 0 ;
}

the output is 123333 (1 2 3 is for what is printed in the loop soon after
initializing it with an object ) .My question is why is the output 3 in
the other case ?(i.e.for b->virt() for i = 0 to 2)
 
M

mlimber

maadhuu said:
The following is a piece of code and the output of the code is pasted after
it . I dont understand how it works (while giving the output) .Can someone
enlighten me on this ?

thanking you .
maadhuu .
the following is the code

class base
{
int data;
public :
base() { }

Don't forget the virtual destructor:

virtual ~base() {}

See this FAQ:

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7
virtual void virt()
{
}
};
class derived:public base
{
int data;
public :
derived(int a):data(a) { }
virtual void virt()
{
std::cout << data ;
}
};


int main()
{
int a = 1;
base *b[3] ;
for(int i = 0; i<3;++i)
{ b = &derived(a++);


Here you have bound a pointer to a temporary object, and consequently,
all bets are off. To fix it, you could do something like:

b = new derived(a++);

(You'd also need to delete them somewhere.)
b->virt();
}
for(int i = 0; i<3;++i)
b->virt();
return 0 ;
}

the output is 123333 (1 2 3 is for what is printed in the loop soon after
initializing it with an object ) .My question is why is the output 3 in
the other case ?(i.e.for b->virt() for i = 0 to 2)


Cheers! --M
 
K

Karl Heinz Buchegger

maadhuu said:
int main()
{
int a = 1;
base *b[3] ;
for(int i = 0; i<3;++i)
{ b = &derived(a++);b->virt();
}
for(int i = 0; i<3;++i)
b->virt();
return 0 ;
}

the output is 123333 (1 2 3 is for what is printed in the loop soon after
initializing it with an object ) .My question is why is the output 3 in
the other case ?(i.e.for b->virt() for i = 0 to 2)



Before you read on, try the following experiment.
Modify one loop in your main() to read as

for(i = 0; i<3;++i) {
std::cout << (void*)b << " " << std::endl;
b->virt();
}

and watch which addresses are stored in the array.



.....



Have you tried it?
What did you notice?

Funny, all the addresses stored in the array are euqal?
So all those pointers 'point to the same object'.
How come?

The problem is here:
{ b = &derived(a++);b->virt();


Here you create a temporary object, store its address in b.
Right when the ';' is reached, something happens.
The temporary gets destroyed!!!
So when the code executes b->virt() it is calling a virtual
function of an object no longer in existence. You were unlucky
that the code didn't crash. But more important: when the creation
loop executes one more time, another temporary is created and as
it happens it is created in the exact same memory location as the
previous one.

That is why all b contain the same address.
 
R

Rolf Magnus

maadhuu said:
The following is a piece of code and the output of the code is pasted
after it . I dont understand how it works (while giving the output) .Can
someone enlighten me on this ?

thanking you .
maadhuu .
the following is the code

class base
{
int data;
public :
base() { }
virtual void virt()
{
}
};
class derived:public base
{
int data;
public :
derived(int a):data(a) { }
virtual void virt()
{
std::cout << data ;
}
};


int main()
{
int a = 1;
base *b[3] ;
for(int i = 0; i<3;++i)
{ b = &derived(a++);


The above statement creates a derived, assigns its address to b, then
destroys the derived.
b->virt();


Here, you get undefined behavior because you acess a non-existent object.
}
for(int i = 0; i<3;++i)
b->virt();


And here again.
 
A

Alf P. Steinbach

* maadhuu:
The following is a piece of code and the output of the code is pasted after
it . I dont understand how it works (while giving the output) .Can someone
enlighten me on this ?

It's not a program that should compile. If a compiler accepts it the output
is not specified by the standard.

class base
{
int data;
public :
base() { }
virtual void virt()
{
}
};
class derived:public base
{
int data;
public :
derived(int a):data(a) { }
virtual void virt()
{
std::cout << data ;
}
};


int main()
{
int a = 1;
base *b[3] ;
for(int i = 0; i<3;++i)
{ b = &derived(a++);b->virt();


Here you take the address of a _temporary_ object and store that address in
b. After the assignment b is a dangling, invalid pointer. Taking the
address of that temporary object should not compile.
}
for(int i = 0; i<3;++i)
b->virt();
return 0 ;
}


If you're using MSVC, which is one compiler that does let you compile this
(via a non-standard extension), add the switch /W4 to the command, or change
your project settings correspondingly, to get warnings about such things.
 
N

Neelesh

I have another problem regarding the virtual functions. I am putting
that in the same thread since it uses the same "address of local
variable" aspect.

#include <iostream>
class base
{
int data;
public :
base() { }
virtual void virt() {
std::cout << "Base version of VF called " << std::endl;
}
virtual ~base() { }


};
class derived:public base
{
int data;
public :
derived(int a):data(a) { }
virtual void virt()
{
std::cout << " Derived Version of VF called " << std::endl;
}
};


int main()
{
base *b = &derived(1);
b->virt();
}

My question is - In this situation (when there is an empty destructor
in the base class), the output is -
"Base Version of VF called"

Whereas if I remove the empty destructor from the base class, then the
output becomes -

"Derived Version of VF called"

Confused. Can somebody explain what I am missing out here?

Thanks in advance
~Neelesh
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top