|
|
It seemed to me like this was a rather simple problem, but for some reason, I can't think up a good way to do this.
Say, I have class Base and class Derived : public Base . I also have a function that takes in a Derived pointer Func(Derived* derived) In my code, I have tried the following:
Base* bPtr = new Base();
Derived* dPtr = dynamic_cast<Derived*>(bPtr);
Func(dPtr);
Unfortunately, this is unsafe, which means that dPtr will always be NULL. Is the only way to do this one that involves using a self-implemented copy constructor that takes in Base* and copies all of the individual members? It seems to me that there must be another solution to something like this... (but I may very well be mistaken)
|
|
|
|
|
If you've only constructed a Base object it can't be a derived object.
The only way to have a Derived object is to create a Derived object (or a class derived from Derived).
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Tell that to all the MFC developers that do things like:
CEdit *pEdit = (CEdit*)GetDlgItem( IDC_EDIT ); And think it is always a real CEdit object that they have on their hands! :P
Newbies: the above will only return a real <small>CEdit</small> pointer in a particular scenario. You only see it used so much because calling <small>CEdit</small> -specific methods works - they are wrappers for <small>SendMessage</small> and do not use any <small>CEdit</small> -specific data members, so you just happen to get away with it. But that does not make it right, and (IMHO) is a really bad habit to get into.
Peace!
--modified at 11:27 Thursday 16th August, 2007 - Mark's Suggestion
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
Ooohh I forgot about that one. Yeah, you need to really know some internals of MFC
to do that
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
You should switch the part of your post in small font to BIG font,
especially the "does not make it right...".
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Heh - done!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
I didn't look at MFC internals, but consider this scenario:
Base *pBase = new Child;
Child *pChild = (Child*)pBase;
What does the pChild refer to? I think a child, not a parent. (I didn't test it yet)
Now take a look at this:
CWnd* pWnd = new CEdit;
...
...
CEdit* pEdit = (CEdit*)GetDlgItem(EDIT_BX);
CWnd* GetDlgItem(UINT blah)
{
return pWnd;
}
if they did something like this, we actually have a pointer to a child.
// "Life is very short and is very fragile also." Yanni while (I'm_alive) { cout<<"I love programming."; }
|
|
|
|
|
In your first scenario, you will have a pointer to a "real" Child object.
In the first part of your second second scenario, pWnd points to a "real" CEdit . In the second part, the underlying object that pEdit refers to depends on what GetDlgItem(...) returns. In your example, it returns the pointer to a real CEdit , although through a CWnd pointer, and it is safe to cast that returned pointer back to a CEdit , because it WAS a CEdit in the first place. In the MFC code, it is a little different as shown below.
The only scenario where it will return a real CEdit object is if one is already in the handle map associated with the EDIT_BX edit control. For example, if you associate a CEdit class with the control using ClassWizard, and you then have it as a data member, then when you call GetDlgItem(...) with that control's identifier, you will get back a pointer to the existing CEdit data member.
If not, meaning that the HWND of the window you are looking for is not already in the handle map, you get back a pointer to a CTempWnd , which never was (and never will be) a CEdit . Additionally, that CTempWnd instance gets destroyed the next time the message pump starts running, which is why the docs say that the returned pointer may be temporary and should not be stored.
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
|
James R. Twine wrote: you get back a pointer to a CTempWnd
So bad. Thanks for the information. From now on, I'll avoid using GetDlgItem . What I see here is really a bad coding style, I think. Finding a window, creating a temp one, and destroying that, is not what I like to happen, when I just need to enable or disable(, etc.) it( Considering the fact that I try this for a lot of controls at the same time.)
Thank you, really informative.
-- modified at 13:32 Thursday 16th August, 2007
// "Life is very short and is very fragile also." Yanni while (I'm_alive) { cout<<"I love programming."; }
|
|
|
|
|
Mark Salsbery wrote: If you've only constructed a Base object it can't be a derived object.
The only way to have a Derived object is to create a Derived object (or a class derived from Derived).
Downcast is OK.
Maxwell Chen
|
|
|
|
|
Of course it is - if the object is actually the type you're downcasting to
It was not in the OP's example.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark, If the derived class does not define any data members then the structure is not changed and therefore the base class can "be" a derived class although you would have to use old style cast or reinterpret_cast as the others are intended to report this as an error. So not saying it's a good idea. Also in most cases the need to up-cast is indicative of a poor design. However when dealing with a library...
|
|
|
|
|
Fine. I guess "can't" was the wrong word.
IMO it's a really bad idea. It requires knowledge of the class one really shouldn't
need to have to know. Plus it makes future additions to the derived class
problematic.
Why would one derive a class and not add anything? Even a virtual function
override is going to add to the class.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: IMO it's a really bad idea.
Yes, as I stated. I have used it to deal with MFC issues in the past. I have never designed it into my own classes.
Mark Salsbery wrote: Why would one derive a class and not add anything? Even a virtual function
override is going to add to the class.
Notice that the virtual override does NOT work (goes to foo) making this a very tenuous situation, but under certain conditions...
class foo
{
int n;
public:
foo(int v){n=v;}
virtual void dump(){cout << "foo: " << n << endl; }
};
class bar : public foo
{
public:
virtual void dump(){cout << "bar: "; dump();}
void dumpex(){cout << "bar: "; dump();}
};
foo* f = new foo(12);
bar* mybar = reinterpret_cast<bar*>(f);
mybar->dump();
mybar->dumpex();
|
|
|
|
|
I'm not disagreeing at all. It just makes me cry a little inside
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: It just makes me cry a little inside
Nah, it's all good. I'm working on some C# I developed last week as we speak. I just noticed some Rube Goldberg stuff I wrote, did a and quickly leveraged the delete key.
|
|
|
|
|
|
Mark Salsbery wrote: Why would one derive a class and not add anything?
Simple. The member functions change from derivation to derivation. In that case, the base class defines the common data, and the member functions in the derived classes define the behavior. You can cast a base class to a derived one to choose behavior.
Note that I'm not advocating doing things this way. This requires that the code 'knows' that the cast is safe. Also, this kind of goes in the reverse direction of the virtual mechanism, which could lead to all sorts of subtle bugs if you combined the two .
Software Zen: delete this;
|
|
|
|
|
|
mark salsbery wrote: Why would one derive a class and not add anything?
I can't believe I asked that! LOL
Still, the downcast kind of implies you need something in the derived class that's not in the base.
It seems like a bad idea, which is probably why RTTI returns NULL on the invalid downcast.
Cheers
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Guess I can't do things this way. I was sort of hoping that there would be default constructors for creating a new derived object with the base object, that would automatically do a hard copy of the data from the base object.
I knew beforehand that my dynamic_cast case would not work, though.
|
|
|
|
|
The only time what you are doing is 'safe' is when Base and Derived have exactly the same data members.
Software Zen: delete this;
|
|
|
|
|
how to create a bar in dialog base application, like how we create in SDI/MDI.
regards
sudhakar
|
|
|
|
|
You cannot just create it and set the dialog class as the parent? Example: http://www.codeproject.com/docking/display_dialog_tooltips.asp[^].
Peace!
-=- James Please rate this message - let me know if I helped or not!<HR> If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|