Alexh
2010-02-01 19:26:08 UTC
Hi all,
I have implemented various graphic elements (classes) which are
derived from a base class. The primary advantage of this is that any
operations on the derived classes can be done via virtual functions
and thus the code that performs the operation does not have to
identify the element (avoids a huge switch statement for every
operation). This is typical polymorphism.
The problem I'm having is modification of existing elements. The
properties of the elements are set up from a dialog (specific to each
type of element) which executes a new statement to create the element.
Since the pointer for element is the base type (and not the derived
class type), it cannot be used to access the derived class variables
which is necessary if the user wants to modify the element options for
an existing element. Here is some basic code -
class CElement : public CObject //base class
{
//vars here
virtual void Draw(...) const {};
CElement() {};
}
class CDog: public CElement //derived class
{
//vars here
virtual void CDog::Draw(...);
CDog(const CDogDlg& DogDlg); //constructor
CDog () {}
};
//implementation code generating Dog
CDogDlg DogDlg;
if (DogDlg.DoModal == IDOK){
CElement* pElement = new CDog(DogDlg);
//save pElement to a CTypedPtrList
}
Later, a user may need to modify an existing Dog. Currently, I do this
by opening DogDlg from a modify menu and on IDOK I delete the
exisiting Dog and simultaneously create a new one from the new dialog
data (delete/replace is transparent to user). The problem arises when
there is more than one Dog because then the dialog may not reflect the
correct data for the selected element (dialog reflects last useage).
Ideally, I would like to have the dialog data reflect that actual data
associated with the Dog I am modifying.
I asked this question on Codeproject and the only possible solution I
got was to use a dynamic_cast operator. I don't necessarily think
there is anything wrong with this but I'd like to see if there are any
other solutuions.
One possibility I thought of is to generate a dialog for each element
so there is a one to one association between element and dialog. This
does not in itself allow the dialog to get data from the derived class
but it obviates the need since it will always retain the last
settings. However, it does not retain the info after a restore from
serialization. I suppose the dialog control states could be serialized
if the dialog pointers are also stored in a CTypedPtrList. Here would
be some possible code -
CDogDlg* pDogDlg = new CDogDlg;
if (pDogDlg->DoModal() == IDOK){
CElement* pElement = new CDog(DogDlg);
//save pElement and pDogDlg to a CTypedPtrList
}
Some other methods that were suggested to me which won't work -
1. Change base class pointer to a derived class pointer. i.e. CDog*
pElement = new .... defeats purpose of polymorphism
2. Define a virtual function that returns the dialog data - problem is
that there are other derived classes with different types of dialog
data (i.e. CCAt, CMouse, etc.). The virtual function prototype
definition has to be consistent for all derived classes.
3. Instantiate the dialog class inside the derived class. This is a
catch 22 since the derived class constructor requires the dialog data.
Thanks for any suggestions.
I have implemented various graphic elements (classes) which are
derived from a base class. The primary advantage of this is that any
operations on the derived classes can be done via virtual functions
and thus the code that performs the operation does not have to
identify the element (avoids a huge switch statement for every
operation). This is typical polymorphism.
The problem I'm having is modification of existing elements. The
properties of the elements are set up from a dialog (specific to each
type of element) which executes a new statement to create the element.
Since the pointer for element is the base type (and not the derived
class type), it cannot be used to access the derived class variables
which is necessary if the user wants to modify the element options for
an existing element. Here is some basic code -
class CElement : public CObject //base class
{
//vars here
virtual void Draw(...) const {};
CElement() {};
}
class CDog: public CElement //derived class
{
//vars here
virtual void CDog::Draw(...);
CDog(const CDogDlg& DogDlg); //constructor
CDog () {}
};
//implementation code generating Dog
CDogDlg DogDlg;
if (DogDlg.DoModal == IDOK){
CElement* pElement = new CDog(DogDlg);
//save pElement to a CTypedPtrList
}
Later, a user may need to modify an existing Dog. Currently, I do this
by opening DogDlg from a modify menu and on IDOK I delete the
exisiting Dog and simultaneously create a new one from the new dialog
data (delete/replace is transparent to user). The problem arises when
there is more than one Dog because then the dialog may not reflect the
correct data for the selected element (dialog reflects last useage).
Ideally, I would like to have the dialog data reflect that actual data
associated with the Dog I am modifying.
I asked this question on Codeproject and the only possible solution I
got was to use a dynamic_cast operator. I don't necessarily think
there is anything wrong with this but I'd like to see if there are any
other solutuions.
One possibility I thought of is to generate a dialog for each element
so there is a one to one association between element and dialog. This
does not in itself allow the dialog to get data from the derived class
but it obviates the need since it will always retain the last
settings. However, it does not retain the info after a restore from
serialization. I suppose the dialog control states could be serialized
if the dialog pointers are also stored in a CTypedPtrList. Here would
be some possible code -
CDogDlg* pDogDlg = new CDogDlg;
if (pDogDlg->DoModal() == IDOK){
CElement* pElement = new CDog(DogDlg);
//save pElement and pDogDlg to a CTypedPtrList
}
Some other methods that were suggested to me which won't work -
1. Change base class pointer to a derived class pointer. i.e. CDog*
pElement = new .... defeats purpose of polymorphism
2. Define a virtual function that returns the dialog data - problem is
that there are other derived classes with different types of dialog
data (i.e. CCAt, CMouse, etc.). The virtual function prototype
definition has to be consistent for all derived classes.
3. Instantiate the dialog class inside the derived class. This is a
catch 22 since the derived class constructor requires the dialog data.
Thanks for any suggestions.