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

child and parent class args

P: n/a
hi

Here's some code:

void SomeFunc(childClass arg);
....

parentClass a;
a=new childClass();
SomeFunc(a);

this spits out an error, it can't convert an object of type parentClass to
childClass. Doesn't work for pointers either. Can anyone shed some light on
how to get this working without casting? In the long run I'll have lots of
childClasses and casting each will become a nightmare.

Cheers
dave
Jul 23 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
David Sobey wrote:
hi

Here's some code:

void SomeFunc(childClass arg);
...

parentClass a;
a=new childClass();
SomeFunc(a);

but a isn't a pointer. So why are you assigning it a pointer?

You want something like:

void somefunc(parent &p) { /* ... */ }

.... {
parent *a = new child();
somefunc(*a);
}

or

.... {
parent p;
somefunc(p);
}

this spits out an error, it can't convert an object of type parentClass to
childClass. Doesn't work for pointers either. Can anyone shed some light on
how to get this working without casting? In the long run I'll have lots of
childClasses and casting each will become a nightmare.
You can't cast the parent to a child. That doesn't make sense (I'm
assuming that parent is the base and child inherits the parent). You can
cast a child to a parent, however (in OO, this is an "is-a" relationship
- the child "is-a" parent).

example:

//---
#include <iostream>

class parent {
public:
parent() { std::cout << __FUNCTION__ << std::endl;}
virtual void hello() { std::cout << "parent" << std::endl; }
};

class child : public parent {
public:
child() { std::cout << __FUNCTION__ << std::endl; }
virtual void hello() { std::cout << "child" << std::endl; }
};

void f(parent& c) { c.hello(); }

int main(int, char**) {

// invalid: x isn't a pointer
// parent x = new child();

parent * x = new child();
f(*x);
delete x;
child y;
f(y);
return 0;
}
//---

Cheers
dave


Hope that made some sense ;)

--
Peter MacMillan
e-mail/msn: pe***@writeopen.com
icq: 1-874-927

GCS/IT/L d-(-)>-pu s():(-) a- C+++(++++)>$ UL>$ P++ L+ E-(-) W++(+++)>$
N o w++>$ O !M- V PS PE Y+ t++ 5 X R* tv- b++(+) DI D+(++)>$ G e++ h r--
y(--)
Jul 23 '05 #2

P: n/a
David Sobey wrote:
hi

Here's some code:

void SomeFunc(childClass arg);
...

parentClass a;
a=new childClass();
a is an object of type parentClass. You can't assign a pointer to it, which
is what new returns. Also, note that a is already a full-blown object. No
need to create another one with new.
SomeFunc(a);
I assume by parentClass, you mean a base class, and childClass is a class
derived from that base class. Then this won't work.
this spits out an error, it can't convert an object of type parentClass to
childClass.
It should give you more errors than that.
Doesn't work for pointers either. Can anyone shed some light
on how to get this working without casting?


It won't work with casting either. Ayway, what are you actually trying to
do? The above code doesn't make much sense. You can't just pass an object
of a base class to a function that expects an object of a class derived
from it, neither by value, nor by pointer or by reference. And casting is
not the solution.

Jul 23 '05 #3

P: n/a
David Sobey wrote:
void SomeFunc(childClass arg);
...

parentClass a;
Congrats on escaping from Java. The above line constructs a complete object
'a', ready to use.
a=new childClass();
SomeFunc(a);

this spits out an error, it can't convert an object of type parentClass to
childClass.
Don't call new unless you need to make an object that lives longer than the
scope of its handle, and always arrange for a delete.
Doesn't work for pointers either. Can anyone shed some light on
how to get this working without casting? In the long run I'll have lots of
childClasses and casting each will become a nightmare.


void SomeFunc(childClass &arg);
SomeFunc(a);

Now, why will you need lots of childClasses? Do they form a pattern that you
could use to collapse into only a few child classes?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 23 '05 #4

P: n/a
On 2005-03-30, David Sobey <ds****@NOSPAMugrad.unimelb.edu.au> wrote:
hi

Here's some code:

void SomeFunc(childClass arg);
...

parentClass a;
a=new childClass();
SomeFunc(a);

this spits out an error, it can't convert an object of type parentClass to
childClass. Doesn't work for pointers either. Can anyone shed some light on
how to get this working without casting? In the long run I'll have lots of
childClasses and casting each will become a nightmare.


Use polymorphism (virtual functions in the parent class) and make the function
take type parentClass&:

void someFunc(parentClass& arg)

then it will dispatch to the override defined in the child class.

This should be explained in the FAQ, look up polymorphism and virtual
functions.

Cheers.
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #5

P: n/a
OK Here's the long and short of it. Num will soon be joined by vector,
matrix, complex etc. It spits out an error
when i try to evaluate the expression, it can't convert a Node pointer to a
Num pointer. I can't cast them, because
when i eventually have at least 5 different child classes of Node, it will
become a nightmare of code to cast for each type.
Any ideas appreciated.

enum Operations {ADD, SUBTRACT};
class Node
{
};
class Num: public Node
{
public:
int val;
static Node operator +(Num l, Num r);
virtual Node Evaluate(Num n);
};
static Num::Node operator +(Num l, Num r)
{
Num result;
result.val=l.val+r.val;
return result;
}
class Branch:public Node
{
public:
Node *left;
Node *right;
enum Operations operation;
Num Evaluate (Num *l, Num *r);
};
Num Branch::Evaluate (Num *l, Num *r)
{
Num result;
if (operation==ADD)
{
result.val=l->val+r->val;
return result;
}
else
{
result.val=l->val-r->val;
return result;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Num l;
l.val=5;
Num r;
l.val=6;
Branch top;
top.left=&(Num)l;
top.right=&(Num)r;
top.operation=ADD;
Node n;
n=top.Evaluate(top.left, top.right);
return 0;
}
Jul 23 '05 #6

P: n/a
David Sobey wrote:

OK Here's the long and short of it. Num will soon be joined by vector,
matrix, complex etc. It spits out an error
when i try to evaluate the expression, it can't convert a Node pointer to a
Num pointer. I can't cast them, because
when i eventually have at least 5 different child classes of Node, it will
become a nightmare of code to cast for each type.
Any ideas appreciated.


You need virtual functions.
In particular the problem you are heading into is know
under the name 'double dispatch'. You need a virtual
function which is selected based on 2 base pointers and
that is something that is not pretty in C++ (C++ does not
directly support that).

Also: You need to decide what should happen if you try to
add a Number with a Matrix. Is that a valid operation? If
yes, how should it be performed? Same with Vector and Matrix
or Vector and Number, all combinations of each with each.

The following implements this for int numbers and double numbers
(Error checking is ommitted for brevity)
It is not pretty, but study it to figure out how this works.

Here is the code (You have been warned)

#include <iostream>
#include <map>
#include <string>
using namespace std;

enum Operations { ADD, SUBTRACT };

class Node;

typedef Node* (*Fnct)( Node* pLeft, Node* pRight );
typedef map< string, Fnct > HandlerMap;

class Dispatcher
{
public:
Node* Evaluate( Node* pLeft, Node* ppRight );
void AddHandler( const type_info& What, const type_info& With, Fnct Handler );

protected:
HandlerMap m_Functions;
};

Dispatcher AddDispatcher;
Dispatcher SubDispatcher;

class Node
{
public:
virtual Node* Evaluate() = 0;
virtual void Output() { cout << "An unknown node\n"; }
};

class IntNumber: public Node
{
public:
IntNumber( int Val )
: m_Value( Val )
{}

Node* Evaluate() { return new IntNumber( *this ); }
void Output() { cout << "An Int: " << m_Value << "\n"; }

int GetValue() { return m_Value; }

protected:
int m_Value;
};

class DoubleNumber: public Node
{
public:
DoubleNumber( double Val )
: m_Value( Val )
{}

Node* Evaluate() { return new DoubleNumber( *this ); }
void Output() { cout << "A Double: " << m_Value << "\n"; }

int GetValue() { return m_Value; }

protected:
double m_Value;
};

class Branch : public Node
{
public:
Branch( Operations Op, Node* pLeft, Node* pRight )
: m_Operation( Op ), m_pLeft( pLeft ), m_pRight( pRight )
{}

Node* Evaluate();

protected:
Node* m_pLeft;
Node* m_pRight;
Operations m_Operation;
};

Node* Branch::Evaluate()
{
Node* pLeftResult = m_pLeft->Evaluate();
Node* pRightResult = m_pRight->Evaluate();
Node* pResult = 0;

if( m_Operation == ADD )
pResult = AddDispatcher.Evaluate( pLeftResult, pRightResult );

else if( m_Operation == SUBTRACT )
pResult = SubDispatcher.Evaluate( pLeftResult, pRightResult );

delete pLeftResult;
delete pRightResult;

return pResult;
}

void Dispatcher::AddHandler( const type_info& What, const type_info& With, Fnct Handler )
{
string Key = What.name();
Key += With.name();
m_Functions[Key] = Handler;
}

Node* Dispatcher::Evaluate( Node* pLeft, Node* pRight )
{
string Key = typeid( *pLeft ).name();
Key += typeid( *pRight ).name();

if( m_Functions.find( Key ) != m_Functions.end() ) {
return (*m_Functions[Key])( pLeft, pRight );
}

cout << "There is no handler for "
<< typeid( *pLeft ).name()
<< " - "
<< typeid( *pRight ).name()
<< endl;

return 0;
}

Node* AddIntInt( Node* pLeft, Node* pRight )
{
IntNumber* pL = dynamic_cast< IntNumber* >(pLeft);
IntNumber* pR = dynamic_cast< IntNumber* >(pRight);

IntNumber* pResult = new IntNumber( pL->GetValue() + pR->GetValue() );

cout << "Adding int + int (->int): "
<< pL->GetValue()
<< " + "
<< pR->GetValue()
<< " -> "
<< pResult->GetValue()
<< endl;

return pResult;
}

Node* AddIntDouble( Node* pLeft, Node* pRight )
{
IntNumber* pL = dynamic_cast< IntNumber* >(pLeft);
DoubleNumber* pR = dynamic_cast< DoubleNumber* >(pRight);

DoubleNumber* pResult = new DoubleNumber( pL->GetValue() + pR->GetValue() );

cout << "Adding int + double (->double): "
<< pL->GetValue()
<< " + "
<< pR->GetValue()
<< " -> "
<< pResult->GetValue()
<< endl;

return pResult;
}

Node* AddDoubleInt( Node* pLeft, Node* pRight )
{
DoubleNumber* pL = dynamic_cast< DoubleNumber* >(pLeft);
IntNumber* pR = dynamic_cast< IntNumber* >(pRight);

DoubleNumber* pResult = new DoubleNumber( pL->GetValue() + pR->GetValue() );

cout << "Adding double + int (->double): "
<< pL->GetValue()
<< " + "
<< pR->GetValue()
<< " -> "
<< pResult->GetValue()
<< endl;

return pResult;
}

Node* SubIntInt( Node* pLeft, Node* pRight )
{
IntNumber* pL = dynamic_cast< IntNumber* >(pLeft);
IntNumber* pR = dynamic_cast< IntNumber* >(pRight);

IntNumber* pResult = new IntNumber( pL->GetValue() - pR->GetValue() );

cout << "Subtracting int - int (->double): "
<< pL->GetValue()
<< " + "
<< pR->GetValue()
<< " -> "
<< pResult->GetValue()
<< endl;
return pResult;
}

int main()
{
AddDispatcher.AddHandler( typeid( IntNumber ), typeid( IntNumber ), AddIntInt );
AddDispatcher.AddHandler( typeid( IntNumber ), typeid( DoubleNumber ), AddIntDouble );
AddDispatcher.AddHandler( typeid( DoubleNumber ), typeid( IntNumber ), AddDoubleInt );

SubDispatcher.AddHandler( typeid( IntNumber ), typeid( IntNumber ), SubIntInt );
IntNumber Num1( 5 );
IntNumber Num2( 7 );
DoubleNumber Num3( 3.0 );

Branch SubExp1( SUBTRACT, &Num1, &Num2 );
Branch Top( ADD, &Num3, &SubExp1 );

Node* pResult = Top.Evaluate();
pResult->Output();
delete pResult;

return 0;
}
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #7

P: n/a
Karl Heinz Buchegger wrote:


The following implements this for int numbers and double numbers
(Error checking is ommitted for brevity)
It is not pretty, but study it to figure out how this works.
[snip long code]

Ooops. I made an error.
Better make the destructor of Node virtual:
class Node
{
public:
virtual ~Node() {}
virtual Node* Evaluate() = 0;
virtual void Output() { cout << "An unknown node\n"; }
};


I am deleting Nodes polymorphically. In this situation
a virtual destructor is a must.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.