Home > Archive > VC Language > November 2005 > casting... at runtime?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
casting... at runtime?
|
|
| hswerdfe 2005-11-24, 7:01 pm |
| This Seems to be pattern I run into a Lot an I don't know how to fix it
without a lot of "else if" statements.
I have several Classes, that look something like this
Class CBase : public CObject{
virtual void CopyFrom(CBase* other);
}
Class CDerived1 : public CBase {
virtual void CopyFrom(CDerived1* other);
}
Class CDerived2 : public CBase {
virtual void CopyFrom(CDerived2* other);
}
Copy From Makes a Copy of All the data in the "other" Object to this Object.
Class CHelper
{
public:
void SetObj(CBase* newVal);
private:
CBase* m_obj;
}
///////////////////////////////
// newVal could be anything
// CBase, CDerived1 , CDerived2....etc
void CHelper::SetObj(CBase* newVal)
{
CRuntimeClass* newClass = newVal->GetRuntimeClass();
CBase* newObj = (CBase*)dragClass->CreateObject();
newObj->CopyFrom(newObj);
}
//this does not work as one might expect
//because the last line Always calls
//CBase::CopyFrom(CBase* other);
//regardless of the runtime class of "newVal".
I can alway change the last line to something like this this
if (newVal->IsKindOf(RUNTIME_CLASS(CDerived1)))
newObj->CopyFrom((CDerived1*) newObj);
if (newVal->IsKindOf(RUNTIME_CLASS(CDerived2)))
newObj->CopyFrom((CDerived2*) newObj);
if (newVal->IsKindOf(RUNTIME_CLASS(CBase)))
newObj->CopyFrom((CBase*) newObj);
Or I could Over ride CopyFrom(CBase* other);
for all the Derived Classes.
but what I REALY would like to do is cast "newVal" to its runtime class
at runtime, without knowing what it will be at compile time.
So how do I case a class to a class at runtime, when I don't know the
class at compile time?
is this possible?
if not is what is the logic behind it?
why is what I want to do a bad idea?
thanks
how
| |
| John Carson 2005-11-24, 7:01 pm |
| "hswerdfe" <hswerdfe@example.com> wrote in message
news:dm57br$3b9$1@nrc-news.nrc.ca
> This Seems to be pattern I run into a Lot an I don't know how to fix
> it without a lot of "else if" statements.
>
> I have several Classes, that look something like this
>
> Class CBase : public CObject{
> virtual void CopyFrom(CBase* other);
> }
> Class CDerived1 : public CBase {
> virtual void CopyFrom(CDerived1* other);
> }
> Class CDerived2 : public CBase {
> virtual void CopyFrom(CDerived2* other);
> }
>
>
> Copy From Makes a Copy of All the data in the "other" Object to this
> Object.
>
> Class CHelper
> {
> public:
> void SetObj(CBase* newVal);
> private:
> CBase* m_obj;
> }
>
> ///////////////////////////////
> // newVal could be anything
> // CBase, CDerived1 , CDerived2....etc
> void CHelper::SetObj(CBase* newVal)
> {
> CRuntimeClass* newClass = newVal->GetRuntimeClass();
> CBase* newObj = (CBase*)dragClass->CreateObject();
What is dragClass?
> newObj->CopyFrom(newObj);
So you are copying from an object to itself?!
Do you mean
newObj->CopyFrom(newVal);
> }
>
> //this does not work as one might expect
> //because the last line Always calls
> //CBase::CopyFrom(CBase* other);
> //regardless of the runtime class of "newVal".
That is what I would expect. Assuming that the function call is indeed
newObj->CopyFrom(newVal);
you haven't overloaded CopyFrom for different arguments, so the function
call is determined solely by the type of the object to which newObj points.
Since newObj points to a CBase object, then of course CBase::CopyFrom will
be called.
More fundamentally, you seem to want to copy a derived class object to a
base class object, while retaining the derived class object's distinctive
character. This doesn't make sense. If the derived class has data members
that the base class lacks, then clearly there is nowhere in the base class
object where you can copy those additional members.
--
John Carson
| |
| Igor Tandetnik 2005-11-24, 9:57 pm |
| "hswerdfe" <hswerdfe@example.com> wrote in message
news:dm57br$3b9$1@nrc-news.nrc.ca...
> This Seems to be pattern I run into a Lot an I don't know how to fix
> it without a lot of "else if" statements.
>
> I have several Classes, that look something like this
>
> Class CBase : public CObject{
> virtual void CopyFrom(CBase* other);
> }
> Class CDerived1 : public CBase {
> virtual void CopyFrom(CDerived1* other);
> }
> Class CDerived2 : public CBase {
> virtual void CopyFrom(CDerived2* other);
> }
>
> Copy From Makes a Copy of All the data in the "other" Object to this
> Object.
>
>
> Class CHelper
> {
> public:
> void SetObj(CBase* newVal);
> private:
> CBase* m_obj;
> }
>
> ///////////////////////////////
> // newVal could be anything
> // CBase, CDerived1 , CDerived2....etc
> void CHelper::SetObj(CBase* newVal)
> {
> CRuntimeClass* newClass = newVal->GetRuntimeClass();
> CBase* newObj = (CBase*)dragClass->CreateObject();
> newObj->CopyFrom(newObj);
> }
I suggest turning your design around a bit:
class CBase : public CObject{
CBase(const CBase&); // regular copy constructor
virtual CBase* Clone() const {return new CBase(*this);}
};
class CDerived1 : public CBase {
CDerived1(const CDerived1&);
virtual CBase* Clone() const {return new CDerived1(*this);}
// Starting from VC7, you can instead write
virtual CDerived1* Clone() const {return new CDerived1(*this);}
// and it's still considered an override for CBase::Clone.
// This feature is called covariant return type
};
class CDerived2 : public CBase {
CDerived2(const CDerived2&);
// showing newer syntax
virtual CDerived2* Clone() const {return new CDerived2(*this);}
};
void CHelper::SetObj(CBase* newVal)
{
CBase* newObj = newVal->Clone();
delete m_obj;
m_obj = newObj;
}
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| hswerdfe 2005-11-28, 7:07 pm |
| >> CBase* newObj = (CBase*)dragClass->CreateObject();
>
>
> What is dragClass?
>
Sorry:
CBase* newObj = (CBase*)newClass->CreateObject();
> So you are copying from an object to itself?!
>
> Do you mean
>
> newObj->CopyFrom(newVal);
again sorry:
yes, yes I did, thank you.
> That is what I would expect. Assuming that the function call is indeed
>
> newObj->CopyFrom(newVal);
>
> you haven't overloaded CopyFrom for different arguments, so the function
> call is determined solely by the type of the object to which newObj
> points. Since newObj points to a CBase object, then of course
> CBase::CopyFrom will be called.
>
> More fundamentally, you seem to want to copy a derived class object to a
> base class object, while retaining the derived class object's
> distinctive character. This doesn't make sense. If the derived class has
> data members that the base class lacks, then clearly there is nowhere in
> the base class object where you can copy those additional members.
>
I agree, The Base Class can not do this.
but if I do this
newObj->CopyFrom((CDerived1*) newVal);
or this
newObj->CopyFrom((CDerived2*) newVal);
I can.
but I don't know which of these cast will work?
So I want to be able to somhow cast without knowing the Class?
In my Minds Eye I see something like this
newObj->CopyFrom(newVal->GetPointerOfClass(newClass));
or
newObj->CopyFrom(newClass->Cast(newVal));
where
GetPointerOfClass, or Cast
returns a pointer of the correct Type.
I am starting to think it is not done,
and I am going to have to live with over riding CopyFrom in all the
derived Classes.
Thanks
How
| |
| hswerdfe 2005-11-28, 7:07 pm |
| Igor Tandetnik wrote:
> "hswerdfe" <hswerdfe@example.com> wrote in message
> news:dm57br$3b9$1@nrc-news.nrc.ca...
>
>
>
> I suggest turning your design around a bit:
>
> class CBase : public CObject{
> CBase(const CBase&); // regular copy constructor
> virtual CBase* Clone() const {return new CBase(*this);}
> };
>
> class CDerived1 : public CBase {
> CDerived1(const CDerived1&);
> virtual CBase* Clone() const {return new CDerived1(*this);}
>
> // Starting from VC7, you can instead write
> virtual CDerived1* Clone() const {return new CDerived1(*this);}
> // and it's still considered an override for CBase::Clone.
> // This feature is called covariant return type
> };
>
> class CDerived2 : public CBase {
> CDerived2(const CDerived2&);
> // showing newer syntax
> virtual CDerived2* Clone() const {return new CDerived2(*this);}
> };
>
> void CHelper::SetObj(CBase* newVal)
> {
> CBase* newObj = newVal->Clone();
> delete m_obj;
> m_obj = newObj;
> }
>
I like this, but:
It does have one Problem.
I usually try to handle Memmory Alocation an deletion in the same Scope.
I alway Thought Clone() worked well for Java Cause deleting Objects is a
non issue.
so now I have an offTopic followup question.
How does one manage to keep from corrupting memory using this method?
Eventually I am going to forget that Clone() alocates memory.
and not Delete it's return pointer after I call it.
| |
| David Wilkinson 2005-11-28, 7:07 pm |
| hswerdfe wrote:
>
> I like this, but:
> It does have one Problem.
> I usually try to handle Memmory Alocation an deletion in the same Scope.
> I alway Thought Clone() worked well for Java Cause deleting Objects is a
> non issue.
>
> so now I have an offTopic followup question.
>
> How does one manage to keep from corrupting memory using this method?
>
> Eventually I am going to forget that Clone() alocates memory.
> and not Delete it's return pointer after I call it.
Use auto_ptr.
HTH,
David Wilkinson
| |
| Igor Tandetnik 2005-11-28, 7:07 pm |
| hswerdfe <hswerdfe@example.com> wrote:
> I like this, but:
> It does have one Problem.
> I usually try to handle Memmory Alocation an deletion in the same
> Scope. I alway Thought Clone() worked well for Java Cause deleting
> Objects is a non issue.
Do you sincerely believe CRuntimeClass::CreateObject manufactures the
object out of thin air, without allocating any memory?
> How does one manage to keep from corrupting memory using this method?
Let me return your question: how do you plan to go about corrupting
memory using this method? I don't see any potential for corruption
necessarily flowing from this method. In any case, it's no more
dangerous than your original technique.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| hswerdfe 2005-11-28, 7:07 pm |
| Igor Tandetnik wrote:
> hswerdfe <hswerdfe@example.com> wrote:
>
>
> Do you sincerely believe CRuntimeClass::CreateObject manufactures the
> object out of thin air, without allocating any memory?
no.
thanks for pointing that out.
>
> Let me return your question: how do you plan to go about corrupting
> memory using this method? I don't see any potential for corruption
> necessarily flowing from this method. In any case, it's no more
> dangerous than your original technique.
I agree it isn't any more dangerous, in fact your way is better.
it is much more clear, and I suppose what I wanted to say was "memmory
leak".
but I think my own error with CRuntimeClass::CreateObject is why I don't
like alocating memory and then not deleteing it in the same scope. I
forgot CRuntimeClass::CreateObject created a new Object.
in a Round about Way I think it calls the default constructror.
any way, currently I think I am going to go with
overriding the CopyFrom object in each of the Derived Classes.
or your Clone() solution I am not sure yet.
both avoid the use of CRuntimeClass, I think using it might have been
yet another mistake on my part.
cheers,
how
|
|
|
|
|