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。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 部分的副本发生在分配期间。

为了使列表是异构的,它必须是一个指针列表,但您还希望避免动态内存分配。如果您小心,您可以避免动态内存分配:

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

但同样,你必须非常小心。该列表现在指向堆栈上的两个对象。如果您从此函数返回,这两个对象将被销毁。请注意,我故意将对象指针列表放在对象之后,这样列表将在对象之前被销毁,因此列表不会指向垃圾。但是,如果您返回列表的副本,您仍然会遇到问题。

于 2012-11-10T16:58:35.117 回答