So here is the deal, I think I need to go another route regarding the pattern I am using but I thought I would get some expert opinions first.
I have a class (UsingClass) that maintains a dynamic list of Base class pointers. When adding a new object to the list I have to figure out what type of object it is because I can't really make it work in a polymorphic manner. The line below tagged "THIS WILL NOT WORK LIKE I WANT IT TO!!" would ideally polymorphically use the =operator from the Derived class of interest, but unfortunately it only uses the default =operator for the Base class.... probably would work if I made Base pure virtual (basically confine it use to an interface with no data members of its own), but I don't really want to have the开发者_运维知识库 Derived classes hold members that are common between both (maybe I need to just cut bait and do it).
I think I may just completely be using the wrong pattern but I don't know what alternatives I should consider.
I know the code does not necessarily compile but please work with me. Thanks in advance!
//code block
class Base {
protected:
int x;
float y;
string type; // default to Derived1 or Dervied2 depending on the object inst
public:
virtual int functionM(int l) = 0;
int functionN(int P);
};
class Derived1 : public Base {
protected:
int a;
public:
int functionM(int l);
float functionR(int h);
};
class Derived2 : public Base {
protected:
int b;
float r;
public:
int functionM(int l);
float functionR(int h);
};
#define MAX_ARRAYSIZE 10
class UsingClass {
private:
Base* myDerived1And2DynamicList[MAX_ARRAYSIZE];
int indexForDynamicList;
public:
void functionAddDerivedToList(*Base myInputPtr) {
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {
if(myInputPtr->type == "Derived1") {
myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived1;
*myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!
} else if (myInputPtr->type == "Derived2") {
myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived2;
*myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!
}
}
} // end of void function
};
Rather than checking the type you could simply add a virtual function to the class 'Base' and call that. This would simplify void functionAddDerivedToList(*Base myInputPtr) to the following:
void functionAddDerivedToList(*Base myInputPtr)
{
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {
myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr->clone();
}
}
Clone would always be implemented to call the class's copy constructor. So in Base, add the following:
virtual Base* clone() = 0;
The implementation would always take this form (example is for Derived1, a subclass of Base in your example):
virtual Base* clone() { return new Derived1(*this); }
One problem I see is that you are sing C-style array to contain a list of "Base" objects. Note that the size of the elements in the array in this case will be the sizof(Base), which is different with sizeof(Derived1) and sizeof(Derived2). Both derives may be different as well. What you can do in this case is to have the array contain pointers of Base objects instead of the actual objects. That will make the size uniformed to 4 bytes and you can access the objects in your array as pointers. Because the array now contain pointers you do not have to determine the type if you simply want to insert them in the array.
void functionAddDerivedToList(Base* myInputPtr)
{
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE)
myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr;
}
If you want to access the object from the array you can do something like this.
Base* p = myDerived1And2DynamicList[index];
p->MyMethod();
You can trust that the correct MyMethod function will be called based on the actual type of p in this case.
I have a class (UsingClass) that maintains a dynamic list of Base class pointers.
Sorry, but you have not (wrong syntax). But don't go that way.
First, give your Base
class a virtual destructor. Otherwise you will experience memory leaks.
Then, redesign your UsingClass
container. Give it a vector of shared_pointer to Base member to hold dynamically alocated polymorphic objects. (If you use a non C++0x-compiler, you can use std::tr1::shared_ptr
.)
class UsingClass {
private:
std::vector<std::shared_ptr<Base> myList;
// int indexForDynamicList; is now myList.size()
public:
void Add(Base* myInputPtr) {
myList.push_back(myInputptr);
}
// ...
};
To add polymorphic objects, use
UsingClass container;
container.add(new Base);
container.add(new Derived1);
container.add(new Derived2);
You can call all polymorphic methods by iterating
for (size_t i = 0; i < myList.size(); ++i)
{
myList->functionM(); // give the function a more "speaking" name
}
By using shared_ptr
you can hold many pointers to one object and don't have to care about freeing memory. Copying the pointers will not copy objects (so called shallow copy). If you really need to copy objects also (so called deep copy), your Base
and derived classes will have to implement a virtual clone()
method.
精彩评论