C ++中的多态性和指针数组问题

时间:2009-12-01 15:21:23

标签: c++ polymorphism

我正在开展一个项目,而且我处于一个我不知道什么是错的阶段。这是简化版本:

代码:

    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

}

问题在于,当在main中,我在创建第一个DerivedB时到达该行,tmp.basePrt [0]已经创建的DerivedA指针会丢失一些。我不知道为什么,但我怀疑这与多态性有关?请帮忙!!谢谢!

编辑:

第一次没有完全正确的代码,对不起......

2 个答案:

答案 0 :(得分:4)

您正在Array Base * b [5]中创建5个对象(DerivedA / B),但是在您的checkList()中,您无权访问这些对象。尝试以某种方式将此数组放入tmp或实例化tmp中的DerivedA / B对象。

在当前形式中,tmp内和main()内的两个数组都没有连接,这就是为什么在运行main()之后你在tmp中仍然有一个空数组。

<强>更新

另请注意,index(无符号整数)成员的类型与循环变量i的类型(当前为整数)匹配。 接下来的尝试是明确地在DerivedA / B中使你的方法virtual(也是析构函数!)。根据编译器的不同,这可能会导致您对baseFunc()的调用仍然解析为Base的'null'主体。 最后,如果它真的是C ++,你可以尝试使用引用,所以你的构造函数看起来像

DerivedA(SomeClassUseBase& tmp) {
  tmp.register(this);
}

请注意点运算符的使用而不是' - &gt;',它使事情更容易阅读和维护。

答案 1 :(得分:3)

for循环的结束括号在哪里?

void checkList() {
    for (int i = 0; i < index ;i++){
        next = basePrt[i];

        next -> baseFunc(); //fails here
    } // this one is missing in the example !

}

使用矢量...

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

};


这对我有用。这不是我为我的项目编写的代码,但它有效。

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