Возможный дубликат:
Переопределение функции родительского класса
Я борюсь с вызовом виртуальной функции в 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, вызывается функция метода объекта. Я предполагаю, что что-то не так с хранением объекта в массиве Objects без динамического выделения памяти для MyObject, но я не уверен.
Есть ли способ вызвать функцию метода MyObject? Как? Между прочим, предполагается, что это гетерогенная коллекция, поэтому наследование на первом месте.
Если нет способа вызвать функцию метода MyObject, то как мне сначала составить мой список?
Также у меня нет доступа к библиотекам за пределами math.h и stdlib.h, поэтому вектор недоступен, например.
Когда вы делаете это:
objects.add(obj);
Вы добавляете копию части объекта MyObject в список, чтобы она больше не была 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);
но опять же, вы должны быть очень осторожны. Список теперь указывает на два объекта в стеке. Если вы вернетесь из этой функции, эти два объекта будут уничтожены. Обратите внимание, что я намеренно поместил список указателей на объекты после объектов, так что список будет уничтожен перед объектами, поэтому список не будет указывать на мусор. Однако, если вы вернете копию списка, у вас все равно будет проблема.
Вы должны хранить указатели в списке. Попробуй это:
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);
Надеюсь это поможет.