By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,652 Members | 1,701 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,652 IT Pros & Developers. It's quick & easy.

typeid and dynamic_cast, gcc 3.3

P: n/a
Hello,

I had been quite suprised by the
following little program:

---- cut ----

#include "iostream.h"

class base {
**public:
**base(){}
**virtual*~base(){};
**void*printType(base***obj);
};

class derived : public base {
**public:
**virtual*void*doIt()
**{
****printType(this);
**}**
};

void base::printType(base * obj) {
**cout*<<*"type*is*"*<<*typeid(obj).name()*<<*endl ;
**cout*<<*dynamic_cast<derived**>(obj)*<<*endl;
}

int main(int argc, char * argv[]) {
**derived*myObj;
**myObj.doIt();
}

---- cut ----

It prints:

type is P4base
0xbfffec00

My expectation was to see "derived" for
the type name.

And even if it is identified as "base"
the RTTI should not be able to dynamic-cast
it to a derived object which it is reported
not to be.

Tested with gcc 3.3 and 3.3.2.

Somebody able to enlighten me?

Greetings,
Andreas
Jul 22 '05 #1
Share this Question
Share on Google+
18 Replies


P: n/a
Andreas Sch. wrote:
Hello,

I had been quite suprised by the
following little program:

---- cut ----

#include "iostream.h"

class base {
public:
base(){}
virtual ~base(){};
void printType(base * obj);
};

class derived : public base {
public:
virtual void doIt()
{
printType(this);
}
};

void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;
This isn't a virtual function, so it will be called with type of 'this'
set to "base", even though it was called from a virtual function
(virtual-ness doesn't pass along the calling sequence, its on a
per-function basis.) Dynamic-casting

cout << dynamic_cast<derived *>(obj) << endl;
I don't see the purpose of doing this: it just prints out the pointer
value. Did you forget to typeid() it?
}

int main(int argc, char * argv[]) {
derived myObj;
myObj.doIt();
}

---- cut ----


--
http://www.it-is-truth.org/

Jul 22 '05 #2

P: n/a
Andreas Sch. wrote:
Hello,

I had been quite suprised by the
following little program:

---- cut ----

#include "iostream.h" this header is not standard - use #include <iostream>

class base {
public:
base(){}
virtual ~base(){}; ^^^^^^^^ ';' not needed
void printType(base * obj);
};

class derived : public base {
public:
virtual void doIt()
{
printType(this);
}
};

void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;
^^^^^^^^^^^^^^^ ... this is the same as

cout << "type is " << typeid( (base *) 0 ).name() << endl;
cout << dynamic_cast<derived *>(obj) << endl;
}

int main(int argc, char * argv[]) {
derived myObj;
myObj.doIt();
}

---- cut ----

It prints:

type is P4base
0xbfffec00

My expectation was to see "derived" for
the type name.

And even if it is identified as "base"
the RTTI should not be able to dynamic-cast
it to a derived object which it is reported
not to be.

Tested with gcc 3.3 and 3.3.2.

Somebody able to enlighten me?


Try this:

class derived;

#include <iostream>
using namespace std;

class base {
public:
base(){}
virtual ~base(){}

template <typename T>
void printType(T * obj)
{
cout << "type is " << typeid(obj).name() << endl;
cout << dynamic_cast<derived *>(obj) << endl;
}
};

class derived : public base {
public:
virtual void doIt()
{
printType(this);
}
};
int main(int argc, char * argv[]) {
derived myObj;
myObj.doIt();
}

Jul 22 '05 #3

P: n/a
Asfand Yar Qazi wrote:
(...)
void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;
This isn't a virtual function, so it will be called with type of 'this'
set to "base", even though it was called from a virtual function
(virtual-ness doesn't pass along the calling sequence, its on a
per-function basis.) Dynamic-casting


Lets see if I got it: typeid does not evaluate the
type information in memory but depends on the type
of the "obj" pointer (and not on what it is pointing to).
cout << dynamic_cast<derived *>(obj) << endl;


I don't see the purpose of doing this: it just prints out the pointer
value. Did you forget to typeid() it?


I just wanted to see if the dynamic_cast fails and
delivers 0x0. I expected it to fail since the typeid-line
printed "base" and not "derived".

Thanks for your answer!
Andreas
Jul 22 '05 #4

P: n/a
Gianni Mariani wrote:
(...)
#include "iostream.h" this header is not standard - use #include <iostream>


Ok...

class base {
(...)
virtual ~base(){};

^^^^^^^^ ';' not needed


Oops, sure.
(...)
void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;


^^^^^^^^^^^^^^^ ... this is the same as

cout << "type is " << typeid( (base *) 0 ).name() << endl;


So typeid delivers the type of the pointer,
not the object.
(...)
Try this:
(...)


That worked. Thank you.

I have been hunting a strange problem in a program
which fails at a dynamic_cast. To debug that situation
I heavily used typeid() and was quite suprised about
its different behavior.

If I am able to shorten the program to a small
example and still produce the same behavior I'll
write that here, too.

Greetings,
Andreas
Jul 22 '05 #5

P: n/a

"Andreas Sch." <no******@yahoo.com> wrote in message
news:bu************@ID-152588.news.uni-berlin.de...
Asfand Yar Qazi wrote:
(...)
void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;


This isn't a virtual function, so it will be called with type of 'this'
set to "base", even though it was called from a virtual function
(virtual-ness doesn't pass along the calling sequence, its on a
per-function basis.) Dynamic-casting


Lets see if I got it: typeid does not evaluate the
type information in memory but depends on the type
of the "obj" pointer (and not on what it is pointing to).


This is a quote from msdn -
<Quote>
If the expression points to a base class type, yet the object is actually of a
type derived from that base class, a type_info reference for the derived class
is the result. The expression must point to a polymorphic type (a class with
virtual functions). Otherwise, the result is the type_info for the static class
referred to in the expression. Further, the pointer must be dereferenced so that
the object it points to is used. Without dereferencing the pointer, the result
will be the type_info for the pointer, not what it points to.
</Quote>

Best wishes,
Sharad

Disclaimer : I know msdn isn't totally accurate at places but not here ;-)
Jul 22 '05 #6

P: n/a

"Sharad Kala" <no*****************@yahoo.com> wrote in message
news:bu************@ID-221354.news.uni-berlin.de...

</snip>
You don't seem to include typeinfo in your code.

Quote from Section 5.2.8.6 of the standard.
" If the header <typeinfo> is not included prior to a use of typeid, the program
is ill-formed. "

Best wishes,
Sharad
Jul 22 '05 #7

P: n/a
Andreas Sch. wrote:
void base::printType(base * obj) {
cout << "type is " << typeid(obj).name() << endl;


^^^^^^^^^^^^^^^ ... this is the same as

cout << "type is " << typeid( (base *) 0 ).name() << endl;


So typeid delivers the type of the pointer,
not the object.


Yes. That's what you asked for. If you provide a pointer to typeid(), it
will tell you that it's a pointer ;-)
If you want info about what the pointer points to, you need to
dereference, i.e typeid(*obj).

Jul 22 '05 #8

P: n/a
Hi!

First of all, thank you all for your valuable
answers to my previous question!

Again, I have a short program illustrating my
(next) problem:

--- snipp ---

#include <typeinfo>
#include <iostream>

class Base
{
public:
Base(){};
virtual ~Base(){};
void calledMethod( Base * a_Base );
};

class Derived : Base
{
public:
Derived() : Base(){};
virtual ~Derived(){};
virtual void callingMethod();
};

void Base::calledMethod( Base * a_base )
{
std::cout << "Parameter is of type \"" << typeid(*a_base).name()
<< "\" at address " << dynamic_cast<Derived *>(a_base)
<< std::endl;
}

void Derived::callingMethod( )
{
std::cout << "I am of type \"" << typeid(*this).name()
<< "\" at address " << dynamic_cast<Derived *>(this)
<< std::endl;
calledMethod( this );
}

int main(int argc, char * argv[])
{
Derived myDerived;
myDerived.callingMethod();
}

/* Program output:

I am of type "7Derived" at address 0xbfffea90
Parameter is of type "7Derived" at address 0

*/

--- snipp ---

The question is: Why is the dynamic_cast in calledMethod()
failing?

RU,
Andreas
Jul 22 '05 #9

P: n/a

"Andreas Sch." <no******@yahoo.com> wrote in message news:bv************@ID-152588.news.uni-berlin.de...
class Derived : Base


You want
class Derived : public Base

I can't even understand why this compiles.
Jul 22 '05 #10

P: n/a
Ron Natalie wrote:
class Derived : Base


You want
class Derived : public Base

I can't even understand why this compiles.


I don't know whether it should compile or not, but this probably is the
reason why it doesn't work. If you derive virtually, Base is not an
accessible base class of Derived.

Jul 22 '05 #11

P: n/a

"Rolf Magnus" <ra******@t-online.de> wrote in message news:bv*************@news.t-online.com...
Ron Natalie wrote:
class Derived : Base


You want
class Derived : public Base

I can't even understand why this compiles.


I don't know whether it should compile or not, but this probably is the
reason why it doesn't work. If you derive virtually, Base is not an
accessible base class of Derived.

You mean privately, not virtually.

The program is ill-formed because you can't call the base class "calledMethod"
function since it's not accessible.
Jul 22 '05 #12

P: n/a
Ron Natalie wrote:
"Rolf Magnus" <ra******@t-online.de> wrote in message news:bv*************@news.t-online.com...
Ron Natalie wrote:

class Derived : Base

You want
class Derived : public Base

I can't even understand why this compiles.


I don't know whether it should compile or not, but this probably is the
reason why it doesn't work. If you derive virtually, Base is not an
accessible base class of Derived.


You mean privately, not virtually.

The program is ill-formed because you can't call the base class "calledMethod"
function since it's not accessible.

It is not ill-formed, to quote 11.2.1 from the standard:
"...If a class is declared to be a base class for another class using
the private access specifier, the public and protected members of the
base class are accessible as private members of the derived class."

Therefore the following code is legal:
class A {
public:
void A_f ( ) { }
};

class B : A {
public:
void f ( ) { A_f ( ); }
};

Michael Mellor
Jul 22 '05 #13

P: n/a
Ron Natalie wrote:

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bv*************@news.t-online.com...
Ron Natalie wrote:
>> class Derived : Base
>
> You want
> class Derived : public Base
>
> I can't even understand why this compiles.
I don't know whether it should compile or not, but this probably is
the reason why it doesn't work. If you derive virtually, Base is not
an accessible base class of Derived.

You mean privately, not virtually.


Of course. Sorry.
The program is ill-formed because you can't call the base class
"calledMethod" function since it's not accessible.


calledMethod is only called by Derived::callingMethod, from where it is
accessible.

Jul 22 '05 #14

P: n/a

"Rolf Magnus" <ra******@t-online.de> wrote in message news:bv*************@news.t-online.com...
calledMethod is only called by Derived::callingMethod, from where it is
accessible.


It is NOT accessible. Base is inherited privately. NONE of it's members
are accessible.

Jul 22 '05 #15

P: n/a
Ron Natalie wrote:
"Rolf Magnus" <ra******@t-online.de> wrote in message news:bv*************@news.t-online.com...
calledMethod is only called by Derived::callingMethod, from where it is
accessible.

It is NOT accessible. Base is inherited privately. NONE of it's members
are accessible.

The derived class can access the base class's public methods or else how
would private inheritence ever be useful?

Michael Mellor
Jul 22 '05 #16

P: n/a
Ron Natalie wrote:
"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bv*************@news.t-online.com...
calledMethod is only called by Derived::callingMethod, from where it
is accessible.


It is NOT accessible. Base is inherited privately. NONE of it's
members are accessible.


....from the "outside world". But from Derived they are. If you derive
privately, public and protected members of Base are private in Derived,
and so they can be called from Derived's member functions. If that
weren't the case, deriving privatly would just be another way of not
deriving at all. Only members that are private in Base are not
accessible to Derived, since private members can only be accessed by
the class itself and to friends.

Jul 22 '05 #17

P: n/a
Ron Natalie schrieb:
"Rolf Magnus" <ra******@t-online.de> wrote (...):
Ron Natalie wrote:
>> class Derived : Base
>
> You want
> class Derived : public Base
>

(...)
I don't know whether it should compile or not, but this probably is the
reason why it doesn't work. If you derive virtually, Base is not an
accessible base class of Derived.

You mean privately, not virtually.
(...)


I tried using public here and yes, it works
as desired.

When deriving privately the outside world should have
problems accessing the base class' members but what
about having a reference to the object?
I may always have a reference to an object which has
only private members (attributes and methods).
In this example the base class tries to cast
a pointer so that it points to a derived object.
Why is this failing?

In other words, I see the effect of deriving public
and know that it should hide the base class members
from being accessed from outside but why does this
affect the dynamic cast?

Greetings,
Andreas
Jul 22 '05 #18

P: n/a
Andreas Schallenberg wrote:
In this example the base class tries to cast
a pointer so that it points to a derived object.
Why is this failing?


dynamic_cast will only succeed if the pointed base class object is
inherited via public inheritance otherwise it fails (C++ std 5.2.7/8).
In such a case use static_cast or C style cast.

Regards,
Janusz

Jul 22 '05 #19

This discussion thread is closed

Replies have been disabled for this discussion.