1

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 SomeClassUseBase(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...

2
  • Just to add some details to the question: an object of SomeClassUseBase will keep an array of ptr to objects from base class, which in runtime will be either DerivedA ptr or DerivedB ptr. The reason calling tmp.register(this) is adding self to that list. And btw, tmp has a public function Base **getTheList(); , which will return the array of pointers to Base objects, again (those will be pointers to DerivedA/B at runtime) Commented Dec 1, 2009 at 16:18
  • 1
    The code, as presented, doesn't compile. Fixing the compiler errors and running it does not exhibit the problem you're experiencing. Perhaps you should check that the example you give demonstrates the problem you're having. Commented Dec 1, 2009 at 16:35

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

+1 Correct, tmp's SomeClassUseBase::register method is never called. Also, am assuming the line "SomeClassUseBase tmp = new SomeClassUseBase(5);" should be "SomeClassUseBase* tmp = new SomeClassUseBase(5);"
@Kosi2801: what do you mean by not having the access? are those just an array of pointers?
SomeClassUseBase::register is called in the constructor of DerivedA and DerivedB, the other one is probably a typo?
@derrdji: Your code-fixes made everything clear now. Another take on the issue: The type of variable in the for-loop should match the uint of the 'index' member. Try 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. Furthermore, if it's really C++, you could try to work with references, so your constructors look like DerivedA(SomeClassUseBase& tmp) and work with the '.' operator instead of the '->' in the constructor.
@Kosi2801 Only the base class need the virtual key word. No compiler should choke on this.
3

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]; 
    }
}

2 Comments

I added some additional info about why using array instead of vector, please check, thank you
@derrdjii So why not return a vector of pointers instead of an array of pointers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.