View Full Version : Why can't I make dynamic_cast work properly?
Hi!
I'm having problem with using RTTI when compiling with gcc 4.0.2.
Is there any flags I should use when compiling? (tried -frtti)
Read somewhere that I should include <typeinfo> in the headers... but in which headers? All headers
in the project?
I thought that it was turned in as default. But when I use dynamic_cast it lets me cast to wathever...
take this for example:
class Thing ( base class, polymorphic )
class Contour class Polygon ( subclasses of Thing )
Thing *thing = new Contour ( );
/* This should work */
Contour *con = dynamic_cast<Contour*) ( thing );
if ( con == NULL )
std::cout<<"con==NULL"<<std::endl;
/* this should return a NULL pointer */
Polygon *pol = dynamic_cast<Polygon*) ( thing );
if ( pol == NULL )
std::cout<<"pol==NULL"<<std::endl;
No of the two returned casts are NULL. From what I understand, the second cast should be NULL since I try to cast a Contour to a Polygon.
This kind of things just makes me sad...
pir
e8johan
31st May 2006, 07:21
It is probably something in you class declarations, could you post the headers please.
Beluvius
31st May 2006, 09:14
Hi,
As far as I can see from you message, the structure is:
class Thing;
class Polygon: public Thing;
class Contour: public Polygon;
The dynamic_cast of a thing to a Polygon is valid AND the dynamic_cast of a thing to a Contour is valid if the thing is originally an instance of a Contour. Simply put: a Contour can be seen as a Contour and as a Polygon. So your code is correct, and it is possible that both dynamic_casts result in a non-NULL pointer.
Hope this helps,
Beluvius
Hi!
Here are the headers. There seems like I did a poor job explaining the class tree. So here is the actual tree. The class I called Polygon is actually called PolygonMesh and Contour is called ContourMesh.
There are two classes in between called Geometrical and Renderable.
Thing <-- Geometrical <-- Renderable <-- ContourMesh
Thing <-- Geometrical <-- Renderable <-- PolygonMesh
The headers of Thing, ContourMesh ( previously called Contour ) and PolygonMesh ( previously called Polygon ) is posted bellow. Since I don't know what you're looing for I've tried to remove as little as possible.
pir
Base class Thing:
#ifndef THING_HEADERFILE041205
#define THING_HEADERFILE041205
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>
namespace thing {
class Thing {
public:
Thing ( std::string sName=Thing::sm_sNAME );
virtual Thing *copy ( ) const = 0;
virtual ~Thing ( );
bool operator== ( const Thing& thing ) const;
bool static equal ( const Thing &thing1, const Thing &thing2 );
friend std::ostream& operator<< ( std::ostream& o,const Thing& thing );
virtual Thing* pickout_component ( int id );
virtual Thing* get_component ( int id );
virtual bool insert_component ( Thing *thing );
virtual bool insert_component_at ( Thing *thing, unsigned int pos );
virtual bool remove_component_at ( unsigned int pos );
void select ( );
void unselect ( );
bool is_selected ( ) const;
bool family_selected ( ) const;
const Thing* get_parent ( ) const;
Thing* get_parent ( );
void set_parent ( Thing* newParent );
virtual int size ( ) const;
virtual const Thing* at ( int nIndex ) const;
virtual Thing* at ( int nIndex );
virtual std::vector<Thing*> get_ThingComponents ( );
private:
static unsigned int sm_nNumCreatedThings;
int m_nId;
std::string m_sName;
bool m_bSaved;
bool m_bSelected;
Thing *m_tParent;
void defaultvalues ( );
static const std::string NAME;
static const bool SAVED;
}; // class Thing
}//namespace thing
#endif // #ifndef THING_HEADERFILE041205
Header of ContourMesh:
#ifndef CONTOURMESH_HEADERFILE041205
#define CONTOURMESH_HEADERFILE041205
#include <vector>
#include <list>
#include "../Renderable/Renderable.h"
#include "./Contour.h"
#include "./contourmeshlib.h"
#include "../FORTRAN__/fortran.h"
#include <GL/glu.h>
namespace contourmesh{
class ContourMesh: public renderable::Renderable{
public:
ContourMesh ( std::string name=sm_sNAME );
ContourMesh ( Contour *first, Contour *last, std::string name=sm_sNAME );
ContourMesh ( const ContourMesh& contmesh );
ContourMesh *copy ( ) const;
~ContourMesh ( );
void delete_contours ( );
const ContourMesh& operator= ( const ContourMesh& contmesh );
friend std::ostream& operator<< ( std::ostream& o, const ContourMesh& cmesh );
bool operator== ( const ContourMesh& cmesh ) const;
static bool equal ( const ContourMesh& pm1, const ContourMesh& pm2 );
Contour* operator[] ( int i );
const Contour *operator[] ( int i ) const;
static std::vector<ContourMesh*> create_meshes(Contour *firstcontour, Contour *lastcontour);
static std::vector<ContourMesh*> divide_mesh(const ContourMesh *cmesh);
void copy_creation_data_to(std::vector<ContourMesh*> &pr_vCD) const;
void insert_contours(Contour *first, Contour *last);
Contour* get_firstcontour ( );
int num_contours ( ) const;
int num_points ( ) const;
bool& selectable ( );
void draw_shape ( GLfloat pr_fWorldScale=1 );
static unsigned int import_into_oneMesh(std::string filename, ContourMesh &cmesh);
static void export_ContourMesh(ContourMesh &cmesh, std::string filename);
virtual bool
cut ( std::vector<Renderable*> *pr_vInside,
std::vector<Renderable*> *pr_vOutside,
bool pr_bOptimizeEdges, bool pr_bThreeDenvelope,
GLfloat **curve, unsigned int ncurve,
GLfloat pr_fWorldRotationX,
GLfloat pr_fWorldRotationY,
GLfloat pr_fWorldRotationZ,
GLfloat pr_fWorldTranslationX,
GLfloat pr_fWorldTranslationY,
GLfloat pr_fWorldTranslationZ,
GLfloat pr_fWorldScaleX,
GLfloat pr_fWorldScaleY,
GLfloat pr_fWorldScaleZ );
void update_boundingbox ( bool bCenterPivots=false );
protected:
std::vector<Contour*> contours;
private:
const static std::string NAME;
static std::string sm_sNAME;
static unsigned int sm_nNumCreatedContourMeshes;
static bool sm_bClassIsSelectable;
void copyContourMesh ( const ContourMesh &cm );
void insert_contour ( Contour &contour );
static void copy_creation_data ( ContourMesh &to,
const ContourMesh &from );
static void check_along ( Contour *tmpcontour, int *along );
static void check_thickness ( ContourMesh &cmesh,
float *new_val, float old, int along );
}; // class ContourMesh
}// namespace contourmesh
#endif // #ifndef CONTOURMESH_HEADERFILE041205
header of PolygonMesh:
#ifndef POLYGONMESH_HEADERFILE021205
#define POLYGONMESH_HEADERFILE021205
#include <stdlib.h>
#include <GL/gl.h>
#include <math.h>
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include "../Renderable/Renderable.h"
#include "./polygonmeshlib.h"
namespace polygonmesh {
class PolygonMesh: public renderable::Renderable {
public:
PolygonMesh ( std::string name = sm_sNAME );
PolygonMesh ( unsigned int *P_arr, GLfloat *V_arr, GLfloat *N_arr,
unsigned int numvert, unsigned int numpol,
std::string name = sm_sNAME );
PolygonMesh ( const PolygonMesh& pmesh );
PolygonMesh *copy ( ) const;
~PolygonMesh ( );
static std::vector<PolygonMesh*> create_meshes ( GLfloat *vertice_array,
GLfloat *normal_array,
unsigned int *polygon_array,
unsigned int numvertices,
unsigned int numpolygons );
static std::vector<PolygonMesh*> divide ( PolygonMesh &bigMesh );
static PolygonMesh* merge ( const std::vector<PolygonMesh*> &meshes );
const PolygonMesh& operator= ( const PolygonMesh& pmesh );
friend std::ostream& operator<< ( std::ostream& o, const PolygonMesh& pmesh );
bool operator== ( const PolygonMesh& pmesh ) const;
static bool equal ( const PolygonMesh& pm1, const PolygonMesh& pm2 );
void draw_shape ( GLfloat pr_fWorldScale=1 );
void copy_creation_data_to ( std::vector<PolygonMesh*> pr_vMD ) const;
GLfloat* get_vertice_array ( );
const GLfloat* get_vertice_array ( ) const;
void set_vertice_array ( GLfloat *newarray );
GLfloat* get_normal_array ( );
const GLfloat* get_normal_array ( ) const;
void set_normal_array ( GLfloat *narr );
bool* get_visible_array ( );
const bool* get_visible_array ( ) const;
void set_visible_array ( bool *varr );
unsigned int* get_polygon_array ( );
const unsigned int* get_polygon_array ( ) const;
void set_polygon_array ( unsigned int *narr );
unsigned int get_number_of_vertices ( ) const;
unsigned int& get_number_of_vertices ( );
unsigned int get_number_of_polygons ( ) const;
unsigned int& get_number_of_polygons ( );
float& get_average ( );
float get_average ( ) const;
float& get_rms ( );
float get_rms ( ) const;
float& get_sigma ( );
float get_sigma ( ) const;
float& get_threshold ( );
float get_threshold ( ) const;
float& get_scale_factor ( );
float get_scale_factor ( ) const;
int& get_sourceid ( );
int get_sourceid ( ) const;
std::string& get_filename ( );
std::string get_filename ( ) const;
bool& selectable ( );
bool selectable ( ) const;
void update_boundingbox ( bool bCenterPivots=false );
protected:
GLfloat *vertice_array;
GLfloat *normal_array;
bool *visible_array;
unsigned int *polygon_array;
unsigned int number_of_vertices;
unsigned int number_of_polygons;
private:
float average;
float rms;
float sigma;
float threshold;
float scale_factor;
int sourceid;
std::string filename;
static bool sm_bClassIsSelectable;
const static std::string NAME;
static std::string sm_sNAME;
static unsigned int sm_nNumCreatedPolygonMeshes;
void copyPolygonMesh ( const PolygonMesh& pmesh );
void zerodefaults ( );
void init_arrays ( int nvertices, int npolygons );
static void copy_creation_data ( PolygonMesh &to, const PolygonMesh &from );
};// class PolygonMesh
}// namespace polygonmesh
#endif //#ifndef POLYGONMESH_HEADERFILE041205
mcosta
31st May 2006, 18:46
Your code seems OK.
Where is the code that fails?
wysota
31st May 2006, 19:00
You might want to try with some simpler code to see if it works at all:
#include <iostream>
class Base {
public:
Base(){}
virtual ~Base(){}
};
class Subclass : public Base {
public:
Subclass():Base(){}
~Subclass(){}
};
class SubSubclass : public Subclass {
public:
SubSubclass():Subclass(){}
~SubSubclass(){}
};
class OtherSubclass : public Base {
public:
OtherSubclass():Base(){}
~OtherSubclass(){}
};
int main(){
Base *o = new SubSubclass();
OtherSubclass *test1 = dynamic_cast<OtherSubclass*>(o);
Subclass *test2 = dynamic_cast<Subclass*>(o);
if(test1) std::cout << "Test 1 failed" << std::endl;
if(!test2) std::cout << "Test 2 failed" << std::endl;
if(!test1 && test2) std::cout << "Dynamic cast ok" << std::endl;
return 0;
}
You're right, its seems like the dynamic_cast is working... when I ran the test program above it printed : Test1 failed. So both casts makes produce a pointer which is not NULL.
Do I need to turn on rtti? If I do, which flag should I use and do I need to compile all code with this flag?
I tried a flag called -frtti ( I think it was called that ).
What should I do now? I have looked at gnus gcc/g++ manual website. But it would be a lie to say that their manuals are the answers to every problem...
pir
wysota
31st May 2006, 23:03
To be honest I just typed "g++ main.cpp -o test" to compile it and it passed both tests.
Here is my "g++ -v":
Using built-in specs.
Target: i586-mandriva-linux-gnu
Configured with: ../configure --prefix=/usr --libexecdir=/usr/lib --with-slibdir=/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --enable-languages=c,c++,ada,f95,objc,java --host=i586-mandriva-linux-gnu --with-system-zlib --enable-long-long --enable-__cxa_atexit --enable-clocale=gnu --disable-libunwind-exceptions --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --enable-gtk-cairo --disable-libjava-multilib
Thread model: posix
gcc version 4.0.1 (4.0.1-5mdk for Mandriva Linux release 2006.0)
Ok, my bad.
I used the same Makefile as for my project before. When I tried "g++ -o main.cpp test" it turned out ok. So the compiler is ok.
Here's the flags I use in my Makefile:
CXXFLAGS = -g -Wall -O0
Does those cause any problems?
I have some FORTRAN code in the project as well. I suppose I have to try to take it away. But is there somebody who know if the extern "C" trick turns dynamic_cast into a pile of shit? I use that to make C++ and FORTRAN to comunicate.
pir
wysota
1st June 2006, 01:13
No, it should only affect bindings. *SHOULD* :)
Ok I found the problem... but not solved it.
The dynamic_cast doesn't work because I use FORTRAN libs when linking the library. There is one lib called -lcxa that mess dynamic_cast up. Anyone have any tips? The fortran compiler is a Intel 9.0.
I love FORTRAN, From Out Rectum Taken Rigmarole And Nogood
pir
wysota
1st June 2006, 15:37
Why don't you use gcc to compile your fortran gizmos? AFAIK gcc supports fortran. Maybe it'll work better.
The FORTRAN code is written for the intel ifort compiler. I don't know much about FORTRAN, but there seems like the syntax for ifort FORTRAN is some kind of mix of FORTRAN90 and FORTRAN75 ( or what they are called )... anyway I don't think that it will compile on any other compiler than on ifort.
But fortunatelly typeid() works just fine, so I can use that in combination with static_cast... Will work for the moment. But I suppose I need to fix this.
thanks
pir
If there is someone who cares about this problem... here is the solution.
check out the link:
http://yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html
This is the part that could save a poor (SA)FORTRAN cursed soul some tears:
Use GNU g++ or Intel C++ compiler to compile and link with main():
g++ -o name-of-exe main_prog.cpp file1.o file2.o -L/opt/intel/fc/9.0/lib -lifport -lifcore -limf -Wabi -Wcast-align
If this can help only one person who has this problem, I'm more than happy.
Powered by vBulletin® Version 4.2.5 Copyright © 2023 vBulletin Solutions Inc. All rights reserved.