Polymorphism and array of pointers problem in C++
I'm working on a project and it's in a stage that I don't know what's wrong. Here's the simplified version:
The code:
class Base { // This base class is pure abstract
public:
virtual ~Base(); // Necessary to trigger destructors in inherited classes
virtual baseFunc() = 0;
};
class DerivedA : public Base{
public:
DerivedA(SomeClassUseBase * tmp){
tmp -> register(this);
}
~DerivedA();
void baseFunc(){
// do something here that's only for DerivedA
}
};
class DerivedB : public Base{
public:
DerivedB(SomeClassUseBase * tmp) {
tmp -> register(this);
}
~DeriveB();
void baseFunc(){
// do something here that's only for DerivedB
}
};
class SomeClassUseBase {
private:
Base ** basePrt;
unsigned int index;
public:
someClassUseBase(int num) {
basePrt = new Base*[num]; //create an array of pointers to the objects
index = 0;
}
void register( Base * base ){
//i tried *(basePrt[index]) = *base, but got the same problem
basePrt[index] = base;
index = index + 1;
}
void checkList() {
for (int i = 0; i < index ;i++){
next = basePrt[i];
next -> baseFunc(); //fails here
}
}
};
int main() {
SomeClassUseBase tmp = new SomeClassUseBa开发者_Python百科se(5);
Base *b[5];
for ( i = 0; i < 5; i += 1 ) {
if ( i % 2 == 0 ) {
b[i] = new DerivedA(&tmp);
}
else {
b[i] = new DerivedB(&tmp);
// the object pointed by tmp::basePrt[0] is lost after this line
} // if
} // for
tmp.checkList(); //crashes here since tmp.bastPrt[0] points to null
}
The problem is that when in main, i reach the line when the first DerivedB is created, the already created DerivedA pointer by tmp.basePrt[0] is lost some how. I don't know why but i suspect that this has sth to do with polymorphism? Please help!! thanks!!
Edit:
Didn't quite get the code correct the first time, sorry...
You are creating the 5 Objects (DerivedA/B) in the Array Base* b[5], but in your checkList() you do not have access to those. Either try to get this array somehow into tmp or instantiate the DerivedA/B objects inside tmp.
In the current form, the two arrays within tmp and within main() are nowhere connected and that's why inside tmp you still have an empty array after running through main().
Update
Check also, that the type of the index
(unsigned integer) member matches the type of your loop variable i
(currently integer).
Next try is to explicitely make your methods in the DerivedA/B also virtual
(also the destructor!). Depending on the compiler this could be an issue that causes your call to baseFunc() still resolve to the Base's 'null' body.
Finally, if it's really C++, you could try to work with references, so your constructors look like
DerivedA(SomeClassUseBase& tmp) {
tmp.register(this);
}
Note the usage of the dot-operator instead of the '->', it makes things a bit easier to read and maintain.
Where is the closing bracket of the for loop?
void checkList() {
for (int i = 0; i < index ;i++){
next = basePrt[i];
next -> baseFunc(); //fails here
} // this one is missing in the example !
}
Use a vector ...
class SomeClassUseBase {
private:
std::vector<Base*> basePrt;
public:
void register( Base * base ){
basePrt.push_back(base);
}
void checkList() {
std::for_each( basePrt.begin(), basePrt.end(), std::mem_fun(&Base::baseFunc);
}
};
This works for me. It's not the code i would write for my projects but it works.
class SomeClassUseBase;
class Base { // This base class is pure abstract
public:
virtual ~Base() {} // Necessary to trigger destructors in inherited classes
virtual void baseFunc() = 0;
};
class DerivedA : public Base {
public:
DerivedA(SomeClassUseBase * tmp){
tmp -> registerIt(this);
}
void baseFunc(){
// do something here that's only for DerivedA
}
};
class DerivedB : public Base {
public:
DerivedB(SomeClassUseBase * tmp){
tmp -> registerIt(this);
}
void baseFunc() {
// do something here that's only for DerivedB
}
};
class SomeClassUseBase {
private:
Base ** basePrt; //Remark: use a vector or shared_array
unsigned int index;
SomeClassUseBase(const SomeClassUseBase&);
const SomeClassUseBase& operator=(const SomeClassUseBase&);
public:
explicit SomeClassUseBase(int num) {
//Remark: Store the size of the container
basePrt = new Base*[num]; //create an array of pointers to the objects
index = 0;
}
~SomeClassUseBase() {
delete[] basePrt;
}
void registerIt( Base * base ) {
//Remark: what if index >= size of the array?
basePrt[index] = base;
index = index + 1;
}
void checkList() const {
for (int i = 0; i < index ;i++){
Base *next = basePrt[i];
next->baseFunc();
}
}
};
int main() {
SomeClassUseBase tmp(5);
Base *b[5]; //Remark: Use a smart_pointer
for ( int i = 0; i < 5; i += 1 ) {
if ( i % 2 == 0 ) {
b[i] = new DerivedA(&tmp);
}
else {
b[i] = new DerivedB(&tmp);
} // if
} // for
tmp.checkList();
for(int i = 0; i < 5; ++i ) {
delete b[i];
}
}
精彩评论