2

重複の可能性:
親クラスの関数をオーバーライドする

C++で仮想関数を呼び出すのに苦労しています。

私はC++の経験がなく、主にC#とJavaを使用しているので、いくつかの妄想があるかもしれませんが、我慢してください。

可能であれば動的メモリ割り当てを回避する必要があるプログラムを作成する必要があります。Listというクラスを作成しました。

template <class T> class List {
public:
    T items[maxListLength];
    int length;


    List() {
        length = 0;
    }

    T get(int i) const {
        if (i >= 0 && i < length) {
            return items[i];
        } else {
            throw "Out of range!";
        }
    };

    // set the value of an already existing element
    void set(int i, T p) {
        if (i >= 0 && i < length) {
            items[i] = p;
        } else {
            throw "Out of range!";
        }
    }

    // returns the index of the element
    int add(T p) {
        if (length >= maxListLength) {
            throw "Too many points!";
        }
        items[length] = p;
        return length++;
    }

    // removes and returns the last element;
    T pop() {
        if (length > 0) {
            return items[--length];
        } else {
            throw "There is no element to remove!";
        }
    }
};

指定されたタイプの配列を作成し、その長さを管理します。

動的メモリ割り当ての必要はありません。次のように書くことができます。

List<Object> objects;
MyObject obj;
objects.add(obj);

MyObjectはフォームObjectを継承します。オブジェクトには、MyObjectでオーバーライドされることになっている仮想関数があります。

struct Object {
    virtual float method(const Input& input) {
        return 0.0f;
    }
};

struct MyObject: public Object {
    virtual float method(const Input& input) {
        return 1.0f;
    }
};

私は要素を次のように取得します:

objects.get(0).method(asdf);

問題は、最初の要素がMyObjectであっても、Objectのメソッド関数が呼び出されることです。MyObjectにメモリを動的に割り当てずに、オブジェクトの配列にオブジェクトを格納することに何か問題があると思いますが、よくわかりません。

MyObjectのメソッド関数を呼び出す方法はありますか?どのように?ところで、それは異種のコレクションであると思われるので、そもそも継承がそこにあるのはそのためです。

MyObjectのメソッド関数を呼び出す方法がない場合、最初にリストを作成するにはどうすればよいですか?

また、math.hとstdlib.hの外部のライブラリにアクセスできないため、たとえばvectorは使用できません。

4

2 に答える 2

4

リストにポインタを格納する必要があります。これを試して:

List<Object*> objects;
Object *obj1 = new Object;
MyObject *obj2 = new MyObject;
Object *obj3 = new MyObject;

objects.add(obj1);
objects.add(obj2);
objects.add(obj3);

// This calls the implementation in Object class
objects.get(0)->method(asdf);

// This calls the implementation in MyObject class
objects.get(1)->method(asdf);

// This calls the implementation in MyObject class
// Polymorphism here
objects.get(2)->method(asdf);

お役に立てれば。

于 2012-11-10T16:59:28.727 に答える
1

これを行うとき:

objects.add(obj);

MyObjectのObject部分のコピーをリストに追加しているため、MyObjectではなくなります。

あなたはこれをやってみたくなるかもしれません:

int add(T const &p) {
    if (length >= maxListLength) {
        throw "Too many points!";
    }
    items[length] = p; // now the problem is here
    return length++;
}

しかし今では、pのオブジェクト部分のコピーが割り当て中に発生します。

リストを異種化するには、ポインタのリストである必要がありますが、動的メモリ割り当てを回避する必要もあります。注意すれば、動的メモリ割り当てを回避できます。

 Object obj1;
 MyObject obj2;
 List<Object*> object_ptrs;
 object_ptrs.add(&obj1);
 object_ptrs.add(&obj2);
 object_ptr.get(1)->method(input);
 object_ptr.get(0)->method(input);

しかし、繰り返しになりますが、非常に注意する必要があります。リストは、スタック上の2つのオブジェクトを指しています。この関数から戻ると、これら2つのオブジェクトは破棄されます。オブジェクトの後にオブジェクトポインタのリストを意図的に配置したことに注意してください。これにより、リストはオブジェクトの前に破棄され、リストがゴミを指しているままになることはありません。ただし、リストのコピーを返す場合でも、問題が発生します。

于 2012-11-10T16:58:35.117 に答える