0

簡単なプログラムがあります

$ cat a.cpp 
#include <iostream>
class MyClass {
    public:
        virtual void check() {
            std::cout << "Inside MyClass\n";
        }
};

class MyClass2: public MyClass {
    public:
        int* a;
        virtual void check() {
            std::cout << "Inside MyClass2\n";
        }
};

int main() {
    MyClass *w, *v;
    w = new MyClass2[2];
    v = new MyClass2;
    std::cout << "Calling w[0].check\n"; w[0].check();
    std::cout << "Calling v->check\n"; v->check();
    std::cout << "Calling w[1].check\n"; w[1].check();
}
$ g++ a.cpp
$ ./a.out 
Calling w[0].check
Inside MyClass2
Calling v->check
Inside MyClass2
Calling w[1].check
Segmentation fault

newを使用して派生クラスオブジェクトを割り当てることは可能だと思いました。また、v-> check()は正常に機能しているようです。

4

3 に答える 3

5
w = new MyClass2[2]; 

MyClass2これにより、2 つのオブジェクトの配列が作成されます。タイプMyClass2[2]です。新しい式は、この配列の最初の要素へのポインターを返し、そのポインターを に割り当てますw

w[1].check();  

これは、オブジェクトの配列としてではなく、オブジェクトwの配列へのポインターとして扱われます。MyClassMyClass2

派生クラス オブジェクトの配列を、基底クラス オブジェクトの配列であるかのように扱うことはできません。派生クラス オブジェクトを使用できるようにする場合は、ポインターの配列が必要です。

MyClass** w = new MyClass*[2];
w[0] = new MyClass2;
w[1] = new MyClass2;
于 2011-02-11T19:35:39.210 に答える
2

@James McNellis と @Nawaz が提案したソリューション (どちらも正しい) の拡張として、利用可能なコンテナー クラスとスマート ポインターを使用することで、多くの混乱を避けることができます。つまりstd::vectorstd::array(コンパイラのバージョンによっては、これはtr1名前空間にある場合もあれば、使用するためにブースト ライブラリをダウンロードする必要がある場合もあります) とshared_ptr(ただし、他にも選択できるものがあります)。

于 2011-02-11T20:04:00.263 に答える
1

ジェームズが姿を消したように見えるので、正しい解決策を投稿する必要があると思います:

MyClass** w = new MyClass*[2]; //Note the difference from James solution!
w[0] = new MyClass2;
w[1] = new MyClass2;

std::cout << "Calling w[0].check\n"; w[0].check();
std::cout << "Calling w[1].check\n"; w[1].check();

これはうまくいくはずです!

于 2011-02-11T19:54:26.667 に答える