@awetlux

Полиморфизм в C++ и как правильно его реализовать с использованием указателя на void?

Описание вопроса объемное, но сам он скорее всего простой. Суть его такова:
Имеем класс интерфейс, базовый класс, два класса-наследника базового. В интерфейсе также имеем виртуальную ф-ю вывода информации, которая "уточняется" в классах-наследниках.
//класс интерфейс
class InterfaceClass{ 
public:
InterfaceClass();
~InterfaceClass();
virtual void output() = 0;
}
//базовый
class Base : public InterfaceClass{
public:
//тут нужные конструкторы
void output(); //выводим a
protected:
int a;
};
//производный
class DerivateOne : public Base{
public:
//тут конструкторы
void output(); //выводим b1 и a
protected:
int b1;
};
//производный
class DerivateTwo : public Base{
public:
//тут конструкторы
void output(); //выводим b2 и a
protected:
int b2;
}

Далее мы хотим создать массив из объектов типа DerivateOne и DerivateTwo непосредственно в main():
...
DerivateOne ArrOne[3]; //массив типа DerivateOne
DerivateTwo ArrTwo[3]; //массив типа DerivateTwo
//инициализируем элементы массива
...


И, собственно, сам вопрос. Пусть у нас есть указатель на void:
void *ptr;
Каким образом пройти по массиву, используя этот самый указатель и адресную арифметику, а именно инкремент (ptr++)?
То бишь вместо:
for (int i = 0; i < 3; i++){
ArrOne[i].output();

Писать что-то в стиле:
ptr = &ArrOne[0]
for (int i = 0; i < 3; i++){
ptr->output();
ptr++;
}

И, соответственно, после этого ptr будет указывать на элементы массива ArrTwo.
Нужно ли привести void *ptr к типу интерфейса (InterfaceClass*), а уже затем станут доступны операции вида ptr++ и подобные действия с выводом?

Спасибо, что дочитали=)
  • Вопрос задан
  • 2543 просмотра
Пригласить эксперта
Ответы на вопрос 4
AtomKrieg
@AtomKrieg
Давай я поищу в Google за тебя
Если в массиве будут сами классы, а не указатели на них, то будет некорректность если размеры классов отличаются (sizeoff) - например разное количество членов класса. Лучше делать так:

vector<Base*> v;
v.push_back(new DerivateOne);
v.push_back(new DerivateTwo);
for(auto b: v)
    b->output();
Ответ написан
gbg
@gbg Куратор тега C++
Любые ответы на любые вопросы
Не надо корячить из C++ C.
Компилятор не настолько тупой, чтобы не заменить индексный оператор на работу с указателем. А вот код вы превратите в помои.

void* в С++ - такая же дрянь. Для этого существуют интерфейсы. Дайте компилятору и оптимизатору поработать.
Ответ написан
ThePyzhov
@ThePyzhov
iOS Ninja
Указатель должен быть на базовый класс, тогда то что вы написали в самом низу, должно работать.
Ответ написан
@alex-t
Прогр. в команде rco.ru
1. Ну еще раз, а то это где-то в комментариях не очевидно. Оператор ++ для указателя должен сместиться на размер объекта. Поэтому 100% правильно будет работать только на конкретном унаследованном классе. А на базовых, тем более интерфейсных, если "сильно повезет".
2. Из примера непонятно, зачем нужно использовать указатель void, вместо итератора по массиву.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы