2012-11-10 2 views
2

Возможный дубликат:
Overriding parent class’s functionКак вызвать виртуальную функцию объекта в C++

я борюсь с вызовом виртуальной функции в 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 наследует форму объекта. Объект имеет виртуальную функцию, которая, как предполагается, должен быть переопределен в 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, метод объекта вызывается функция. Я предполагаю, что что-то не так с сохранением объекта в массиве объектов без динамического выделения памяти для MyObject, но я не уверен.

Есть ли способ вызвать функцию метода MyObject? Как? Предполагается, что это гетерогенная коллекция btw, поэтому именно поэтому наследование существует.

Если нет способа вызвать функцию метода MyObject, то как мне сделать свой список в первую очередь?

Также у меня нет доступа к библиотекам за пределами math.h и stdlib.h, поэтому вектор недоступен, например.

+3

Нарезка объектов всегда весело. Вам нужен список указателей. – chris

+0

http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c для какой резки – Mat

ответ

1

Когда вы сделаете это:

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

но теперь копия части объекта р происходит в процессе выполнения задания.

Чтобы сделать список гетерогенным, он должен быть списком указателей, но вы также хотели избежать распределения динамической памяти. Вы можете избежать динамического распределения памяти, если будете осторожны:

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

но опять же, вы должны быть очень осторожны. Список теперь указывает на два объекта в стеке. Если вы вернетесь из этой функции, эти два объекта будут уничтожены.Обратите внимание, что я целенаправленно ставил список объектов указателей после объектов, так что список будет уничтожен перед объектами, поэтому список не останется указывать на мусор. Однако, если вы вернете копию списка, у вас все равно возникнет проблема.

+0

Что делать, если функция add имеет параметр add (T & p)? – SoonDead

+1

@SoonDead: Это просто отложит проблему до назначения. Когда вы говорите 'items [length] = p', вы просто будете копировать объектную часть p. –

+0

Функциональная подпись прекрасна, но она добавляется в список, добавленный в список ... – Caribou

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

Надеюсь, это поможет.

+0

Я закончил тем, что принял другой ответ, поскольку было довольно хорошее объяснение того, что там происходит, но этот ответ также помог. – SoonDead

+0

Рад, что вы поняли это. –

 Смежные вопросы

  • Нет связанных вопросов^_^