473,385 Members | 1,707 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

typeid and dynamic_cast, gcc 3.3

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
18 2796
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
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
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
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

"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

"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
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
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

"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
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

"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
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
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

"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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Jamie Burns | last post by:
Hello, I just did a simple benchmark: for (xx=0;xx<100000;xx++) { rDerived* derived = dynamic_cast<rDerived*>(object); if (derived) derived->setValue(message.data.messageSetInt.value); } ...
19
by: Marco Jez | last post by:
Hi everyone! I would like to use the reference returned by typeid as key in a std::map. Is it safe to assume that typeid(T) (where T is a type name) will always return the same reference to the...
18
by: Adam Zimny | last post by:
This is fragment of code from Bruce Eckel's Thinking in c++ ( last 3 couts are mine to show what happened ). The question is: is Bruce Eckel wrong or g++ ( my version is 3.2.3 ) is buggy ? //:...
11
by: mscava | last post by:
Here are my classes. Each of them has virtual destructor: class Object { ... }; class Door : public Object { ... }; class ClosedDoor : public Door { ... }; class OpenedDoor : public Door { ......
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.