|
-
November 13th, 2003, 08:24 AM
#1
multi-inheritance & cast
Hi,
I have a strange problem.
Firstly let me figure out my classes.
class IQueable //abstract class, i.e. interface
{
virtual int GetPriority() = 0; //pure virtual fnc.
};
class CQueue()//real class; implemented
{
void Enqueue( IQueable* apElem );
IQueable* Dequeue( IQueable* apElem );
...
};
class CBaseTask //real base class; implemented
{
int GetStatus();
void SetStatus( int anStat );
int m_nStatus; //default is initialized 0.
};
//real multi-inherited class; implemented
class CDerivedQueableTask : public CBaseTask, public IQueable
{
virtual int GetPriority(){ return 2; };
...
}
void main()
{
CQueue* pQueue = new CQueue();
CDerivedQueableTask* pTask = new CDerivedQueableTask();
pTask->SetStatus( 1 );
//the above task is deriven from IQueable
pQueue->Enqueue( pTask );
CBaseTask* pBT = (CBaseTask*)pQueue->Dequeue();
//the above base is not deriven from IQueable,
//but I am sure that it is CDerivedQueableTask which implemets IQueable.
//it is just a few line above...
pBT->GetStatus(); //returns some meaningless value; e.g. 701356
}
As you see if I cast the dequeued object( CDerivedQueableTask ) to CTask, I get inconsistent result.
If I change it to the following, it works!
CDerivedQueableTask* pTask = (CDerivedQueableTask*)pQueue->Dequeue();
What may be the problem ?
Last edited by the one; November 13th, 2003 at 08:29 AM.
-
November 13th, 2003, 08:33 AM
#2
I could first try it with the dynamic_cast operator instead of the C-style casting.
So something like this:
Code:
CBaseTask* pBT = dynamic_cast<CBaseTask*>(pQueue->Dequeue());
and see if that works.
-
November 13th, 2003, 08:36 AM
#3
it is more dangerous.. it works wrong and whenever I want to touch my exe it asserts..
please note that the above code is just a toy-version of my app.
but it is one-to-one regarding the sckeleton
-
November 13th, 2003, 08:39 AM
#4
mm, i had a second look at your code and the Dequeu function returs a IQueable* object. CBaseTask does not inherit from IQueable, so i think that's the problem.
Why don't you let CBaseTask derive from IQueable?
-
November 13th, 2003, 08:46 AM
#5
Firstly thanks for your replies..
CBaseTask does not inherit from IQueable
But we know that it is actually a IQueable. Because it is created as CDerivedQueableTask....
Why don't you let CBaseTask derive from IQueable?
As a character, CTask doesn't have to be queued. But CDerivedQueableTask should. These are just dummy classes I wrapped here, I mean I couldn't make CTask as IQueable, it violets me in many where... ( you know, I couldn't explaine whole the project here )
Any more help?
-
November 13th, 2003, 08:53 AM
#6
Originally posted by the one
it is more dangerous.. it works wrong and whenever I want to touch my exe it asserts..
It does this because you are trying to cast something to a non-related type. It's not more dangerous, it is safer because it is preventing you from doing something that you shouldn't. I'm guessing that dynamic_cast is returning NULL, and this is causing you problems.
MSDN for dynamic_cast:
When you use dynamic_cast < type-id > ( expression ), if expression cannot be safely converted to type type-id, the run-time check causes the cast to fail. For example:
Code:
class A { ... };
class B { ... };
void f()
{
A* pa = new A;
B* pb = dynamic_cast<B*>(pa); // fails, not safe;
// B not derived from A
...
}
The value of a failed cast to pointer type is the null pointer.
Thought for the day/week/month/year:
Windows System Error 4006:
Replication with a nonconfigured partner is not allowed.
-
November 13th, 2003, 08:57 AM
#7
My original code is not dynamic_cast. It is pure casting.. ( C type )
(CTask*)pQueue->Dequeue();
-
November 13th, 2003, 09:01 AM
#8
Originally posted by the one
My original code is not dynamic_cast. It is pure casting.. ( C type )
(CTask*)pQueue->Dequeue();
Right. This is dangerous for the reason(s) outlined in my previous post. dynamic_cast is safer because it isn't a "force cast" - it fails if expression cannot be converted to the type speficied by typeid. You are trying to do something unsafe with "(CTask*)pQueue->Dequeue();" (or whatever the cast of the day appears to be), and you are seeing the results with your "meaningless value".
Thought for the day/week/month/year:
Windows System Error 4006:
Replication with a nonconfigured partner is not allowed.
-
November 13th, 2003, 09:04 AM
#9
but why doesn't 'force cast' cast it correctly ? They are valid object as you see..
-
November 13th, 2003, 09:13 AM
#10
Originally posted by the one
but why doesn't 'force cast' cast it correctly ? They are valid object as you see..
Valid objects, but not derived from a common base class. You can't just force an object to being of another type. You can only cast upward (always)or downward (sometimes) in the class hierarchy.
-
November 13th, 2003, 09:17 AM
#11
Originally posted by the one
but why doesn't 'force cast' cast it correctly ? They are valid object as you see..
Since you're changing classes (What's a CTask*? It's not referenced/defined in your original post...), it may be difficult to get on common ground, but going off of:
Code:
CBaseTask* pBT = (CBaseTask*)pQueue->Dequeue();
pBT->GetStatus();
from the original post...
pQueue is of type CQueue*.
CQueue::Dequeue returns an IQueable*.
CBaseTask does not derive from IQueable. You are trying to force a CBaseTask to be an IQueable, and the types are not related to each other. A force cast does cast it "correctly" in the sense that you can call methods on the object. But this behavior is undefined. Depending on what the "GetStatus" method does, you could have an access violation immediately, or not see anything bad happen at all (aside from the "meaningless value").
Don't do what you're trying to do.
Code:
//the above base is not deriven from IQueable,
//but I am sure that it is CDerivedQueableTask which implemets IQueable.
Then change the code to:
Code:
CDerivedQueableTask* pDQT = dynamic_cast< CDerivedQueableTask* >( pQueue->Dequeue() );
Or make CBaseTask inherit from IQueable.
Thought for the day/week/month/year:
Windows System Error 4006:
Replication with a nonconfigured partner is not allowed.
-
November 13th, 2003, 09:31 AM
#12
[QUOTE]Originally posted by the one
it is more dangerous.. it works wrong and whenever I want to touch my exe it asserts..
I think that is the point.
dynamic_cast is not dangerous, it just don't allow you to cast something that is not possible.
So, if you apply C-style cast, you may become garbage.
dynamic_cast <> will return NULL instead, so you can test your returned pointer and find out if it is valid or not.
I think the problem is in the
class CDerivedQueableTask : public CBaseTask, public IQueable
that inherits from two base-classes.
It's hard to describe on this piece of code, but CBaseTask and IQueable, although both are base classes for CDerivedQueableTask, one do not know about another, so cast fails.
dynamic_cast shows you the problem, you can't ignore it.
-
November 13th, 2003, 09:36 AM
#13
Thanks..
I'will regard these.
I may refine my design..
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|