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

casting to a derived class

P: n/a
I need to make software engineering decision to do with using a
derived data type in a container class. So for example, if I have an
Edge class, and I want to make a Edge object which contains two
NumberVertices instead of Vertices, I can either just use a non-
templated Edge class which stores pointers to my NumberVertices and
leave it up to the programmer to cast back again to NumberVertex (this
type of casting only works with pointers), or I can use a template
class.

I've been looking around on info on this, and I can't decide which is
a better approach. I find using template classes gives you very
difficult to interpret error messages, but I wonder if using this
pointer/static cast approach will give me some typing problems later
on.

/************************************************** *
* Using pointers and static casts to to access objects of derived
class:
************************************************** **/
#include <iostream>
class Vertex
{
public:
Vertex(void){};
};
class NumberVertex :
public Vertex
{
public:
NumberVertex(void){};
NumberVertex(int num):number(num){};
int getNum(){return number;}
public:
~NumberVertex(void){};
protected:
int number;
};

class Edge
{
public:
Edge(Vertex* a, Vertex* b):v1(a),v2(b){};
Vertex* getV1(){return v1;}
Vertex* getV2(){return v2;}
protected:
Vertex* v1;
Vertex* v2;
};

int main(int argc, char **argv){
NumberVertex* v1 = new NumberVertex(1);
NumberVertex* v2 = new NumberVertex(2);
Edge e(v1, v2);

NumberVertex* ev1 = (NumberVertex*) e.getV1();
NumberVertex* ev2 = (NumberVertex*) e.getV2();

std::cout << "V1: " << ev1->getNum() << std::endl;
std::cout << "V2: " << ev2->getNum() << std::endl;

}
/************************************************** *
* Using template class:
************************************************** **/
#include <iostream>

class Vertex
{
public:
Vertex(void){};
};

class NumberVertex :
public Vertex
{
public:
NumberVertex(void){};
NumberVertex(int num):number(num){};
int getNum(){return number;}
public:
~NumberVertex(void){};
protected:
int number;
};

template <class Vertclass Edge
{
public:
Edge(Vert& a, Vert& b):v1(a),v2(b){};
Vert& getV1(){return v1;}
Vert& getV2(){return v2;}
protected:
Vert v1;
Vert v2;
};

Jun 19 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Naomi wrote:
I need to make software engineering decision to do with using a
derived data type in a container class. So for example, if I have an
Edge class, and I want to make a Edge object which contains two
NumberVertices instead of Vertices, I can either just use a non-
templated Edge class which stores pointers to my NumberVertices and
leave it up to the programmer to cast back again to NumberVertex (this
type of casting only works with pointers), or I can use a template
class.

I've been looking around on info on this, and I can't decide which is
a better approach. I find using template classes gives you very
difficult to interpret error messages, but I wonder if using this
pointer/static cast approach will give me some typing problems later
on.
What you're comparing is "run-time polymorphism" versus "compile-
time polymorphism". I bet if you search for those, you will find
more information which one is more appropriate in what case.
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 19 '07 #2

P: n/a

Naomi <na*******@gmail.comwrote in message ...
>
#include <iostream>
class Vertex{ public:
Vertex(){}; // (void) not needed in C++
virtual ~Vertex(){}; // suggestion
};

class NumberVertex : public Vertex { public:
NumberVertex(){}; // (void) not needed in C++
NumberVertex( int num ) : number( num ){};
int getNum(){ return number;}
public:
~NumberVertex(){}; // (void) not needed in C++
protected:
int number;
};

class Edge{ public:
Edge( Vertex *a, Vertex *b ) : v1( a ), v2( b ){};
Vertex* getV1(){ return v1;}
Vertex* getV2(){ return v2;}
protected:
Vertex *v1;
Vertex *v2;
};

int main(int argc, char **argv){
NumberVertex *v1 = new NumberVertex( 1 );
NumberVertex *v2 = new NumberVertex( 2 );
Edge e( v1, v2 );
// NumberVertex* ev1 = (NumberVertex*) e.getV1();
// NumberVertex* ev2 = (NumberVertex*) e.getV2();

// Why hide a possible error with a 'C' style cast?

NumberVertex *ev1 = dynamic_cast<NumberVertex*>( e.getV1() );
if( not ev1 ){ std::cout << "ERROR\n"; return EXIT_FAILURE; }
// ...etc.
>
std::cout << "V1: " << ev1->getNum() << std::endl;
std::cout << "V2: " << ev2->getNum() << std::endl;
}
--
Bob R
POVrookie
Jun 19 '07 #3

P: n/a
On Jun 19, 8:53 pm, Naomi <naomi....@gmail.comwrote:
I need to make software engineering decision to do with using a
derived data type in a container class. So for example, if I have an
Edge class, and I want to make a Edge object which contains two
NumberVertices instead of Vertices, I can either just use a non-
templated Edge class which stores pointers to my NumberVertices and
leave it up to the programmer to cast back again to NumberVertex (this
type of casting only works with pointers), or I can use a template
class.

I've been looking around on info on this, and I can't decide which is
a better approach. I find using template classes gives you very
difficult to interpret error messages, but I wonder if using this
pointer/static cast approach will give me some typing problems later
on.

/************************************************** *
* Using pointers and static casts to to access objects of derived
class:
************************************************** **/
#include <iostream>

class Vertex
{
public:
Vertex(void){};

};

class NumberVertex :
public Vertex
{
public:
NumberVertex(void){};
NumberVertex(int num):number(num){};
int getNum(){return number;}
public:
~NumberVertex(void){};
protected:
int number;

};

class Edge
{
public:
Edge(Vertex* a, Vertex* b):v1(a),v2(b){};
Vertex* getV1(){return v1;}
Vertex* getV2(){return v2;}
protected:
Vertex* v1;
Vertex* v2;

};

int main(int argc, char **argv){
NumberVertex* v1 = new NumberVertex(1);
NumberVertex* v2 = new NumberVertex(2);
Edge e(v1, v2);

NumberVertex* ev1 = (NumberVertex*) e.getV1();
NumberVertex* ev2 = (NumberVertex*) e.getV2();

std::cout << "V1: " << ev1->getNum() << std::endl;
std::cout << "V2: " << ev2->getNum() << std::endl;

}

/************************************************** *
* Using template class:
************************************************** **/
#include <iostream>

class Vertex
{
public:
Vertex(void){};

};

class NumberVertex :
public Vertex
{
public:
NumberVertex(void){};
NumberVertex(int num):number(num){};
int getNum(){return number;}
public:
~NumberVertex(void){};
protected:
int number;

};

template <class Vertclass Edge
{
public:
Edge(Vert& a, Vert& b):v1(a),v2(b){};
Vert& getV1(){return v1;}
Vert& getV2(){return v2;}
protected:
Vert v1;
Vert v2;

};- Hide quoted text -

- Show quoted text -
it depends on how you are going to use it. if v1 and v2 may contain
different types of vertice then the former approach is somehow better,
otherwise the later is better.But if the number of vertex types
derived form 'Vertex' is many and lots of member functions are
prepared for 'Edge' and v1 and v2 are supposed to contain vertice of
the same type.then you may derive a template from a pointer-using
'Edge'.

Jun 19 '07 #4

P: n/a
On Jun 19, 4:49 pm, terminator <farid.mehr...@gmail.comwrote:
it depends on how you are going to use it. if v1 and v2 may contain
different types of vertice then the former approach is somehow better,
otherwise the later is better.
IMNSHO, nothing could possibly be worse than performing a cast to a
derived class. In 99% of situations, there is a way to code around it.

Jun 19 '07 #5

P: n/a
On Jun 20, 1:59 am, Zachary Turner <divisorthe...@gmail.comwrote:
On Jun 19, 4:49 pm, terminator <farid.mehr...@gmail.comwrote:
it depends on how you are going to use it. if v1 and v2 may contain
different types of vertice then the former approach is somehow better,
otherwise the later is better.

IMNSHO, nothing could possibly be worse than performing a cast to a
derived class. In 99% of situations, there is a way to code around it.
I agree but I am used to follow a rule that says :"do the hard/dirty
things just once".I mean something like this:
class edge{//hard thing
// put big member functions here.
};

template <class vert>
struct tedge:edge{//dirty thing
/*just define the inline interface that perform casts and call
edge::functions*/
};

regards,
FM.

Jun 20 '07 #6

P: n/a
terminator wrote:
Zachary Turner <divisorthe...@gmail.comwrote:
>IMNSHO, nothing could possibly be worse than performing a cast to a
derived class. In 99% of situations, there is a way to code around it.

I agree but I am used to follow a rule that says :"do the hard/dirty
things just once".I mean something like this:
class edge{//hard thing
// put big member functions here.
};

template <class vert>
struct tedge:edge{//dirty thing
/*just define the inline interface that perform casts and call
edge::functions*/
};
Why do you need to cast to call base class' functions?

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Jun 20 '07 #7

P: n/a
On Jun 20, 6:48 pm, "Thomas J. Gritzan" <Phygon_ANTIS...@gmx.de>
wrote:
terminator wrote:

Zachary Turner <divisorthe...@gmail.comwrote:


IMNSHO, nothing could possibly be worse than performing a cast to a
derived class. In 99% of situations, there is a way to code around it.
I agree but I am used to follow a rule that says :"do the hard/dirty
things just once".I mean something like this:
class edge{//hard thing
// put big member functions here.
};
template <class vert>
struct tedge:edge{//dirty thing
/*just define the inline interface that perform casts and call
edge::functions*/
};

Why do you need to cast to call base class' functions?

--
Thomashttp://www.netmeister.org/news/learn2quote.html- Hide quoted text -

- Show quoted text -
IMHO it is really dirty to put a casting on every line that uses
'edge',so I decided to put the dirty part in the definition of the
'tedge' template.I dont know how the compiler handles templates behind
the scene ,so I decide to put the working part of the code in 'edge'
in order to decrease the code size(I think that templates increase the
code size ) because we are going to use the template for objects of
the same herarchy graph and we are just considering the behavior of
the Grand base type.

regards,
FM

Jun 23 '07 #8

P: n/a
On 23 Jun, 10:28, terminator <farid.mehr...@gmail.comwrote:
On Jun 20, 6:48 pm, "Thomas J. Gritzan" <Phygon_ANTIS...@gmx.de>
wrote:
terminator wrote:
Zachary Turner <divisorthe...@gmail.comwrote:
>IMNSHO, nothing could possibly be worse than performing a cast to a
>derived class. In 99% of situations, there is a way to code around it.
Zachary's comment (and the preceding discussion) is about casting
*from* a base class *to* a derived class.
I agree but I am used to follow a rule that says :"do the hard/dirty
things just once".I mean something like this:
class edge{//hard thing
// put big member functions here.
};
template <class vert>
struct tedge:edge{//dirty thing
/*just define the inline interface that perform casts and call
edge::functions*/
};
Why do you need to cast to call base class' functions?

IMHO it is really dirty to put a casting on every line that uses
'edge',so I decided to put the dirty part in the definition of the
'tedge' template.I dont know how the compiler handles templates behind
the scene ,so I decide to put the working part of the code in 'edge'
in order to decrease the code size(I think that templates increase the
code size ) because we are going to use the template for objects of
the same herarchy graph and we are just considering the behavior of
the Grand base type.
You don't seem to have answered the question. The original discussion
was about casting from base to derived. You are now talking about
calling base class functions from a derived class.

1. That's the other way around - you do understand that's a completely
different question don't you?
2. Why do you need to cast to go that way?

class edge
{
public:
void foo()
{ /* hard thing - big member function */ }
};

template <class vert>
struct tedge : edge
{
// Dirty thing - apparently, but what's dirty about it, and where
is the need for a cast?
void foo() { edge::foo(); }
};

Gavin Deane

Jun 23 '07 #9

P: n/a
On Jun 23, 1:47 pm, Gavin Deane <deane_ga...@hotmail.comwrote:
On 23 Jun, 10:28, terminator <farid.mehr...@gmail.comwrote:
On Jun 20, 6:48 pm, "Thomas J. Gritzan" <Phygon_ANTIS...@gmx.de>
wrote:
terminator wrote:
Zachary Turner <divisorthe...@gmail.comwrote:
IMNSHO, nothing could possibly be worse than performing a cast to a
derived class. In 99% of situations, there is a way to code around it.

Zachary's comment (and the preceding discussion) is about casting
*from* a base class *to* a derived class.


I agree but I am used to follow a rule that says :"do the hard/dirty
things just once".I mean something like this:
class edge{//hard thing
// put big member functions here.
};
template <class vert>
struct tedge:edge{//dirty thing
/*just define the inline interface that perform casts and call
edge::functions*/
};
Why do you need to cast to call base class' functions?
IMHO it is really dirty to put a casting on every line that uses
'edge',so I decided to put the dirty part in the definition of the
'tedge' template.I dont know how the compiler handles templates behind
the scene ,so I decide to put the working part of the code in 'edge'
in order to decrease the code size(I think that templates increase the
code size ) because we are going to use the template for objects of
the same herarchy graph and we are just considering the behavior of
the Grand base type.

You don't seem to have answered the question. The original discussion
was about casting from base to derived. You are now talking about
calling base class functions from a derived class.

1. That's the other way around - you do understand that's a completely
different question don't you?
2. Why do you need to cast to go that way?

class edge
{
public:
void foo()
{ /* hard thing - big member function */ }

};

template <class vert>
struct tedge : edge
{
// Dirty thing - apparently, but what's dirty about it, and where
is the need for a cast?
void foo() { edge::foo(); }

};

Gavin Deane- Hide quoted text -

- Show quoted text -
'tedge' needs to call some functions from base ('foo' as you wrote)
particularly the ctor/dtor inline.the parameter type('vert') to
'tedge' must be derived from 'vertex'(the grand base for parameter
types) and this template is supposed to handle downward castings so
that there is not a need for down cast from a 'vertex' in every line
that contains a call to 'edge' functions.So the 'tedge' is supposed to
do the dirty portion of the code(down casts) and 'edge' does the hard
thing('foo').

regards,
FM

Jun 24 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.