Полиморфизм времени выполнения с указателями в C++
Я застрял с проблемой назначения указателя времени выполнения в C++. у меня естьbase
класс с 2 членами темы и темы.
class base {
struct base_struct {
int a;
};
base_struct thread;
std::vector<base_struct> threads;
void fn () {}
};
derived1
происходит от base
и имеет те же два члена (thread
а такжеthreads
) но другого типа.
class derived1 : public base {
struct derived_struct11 : public base_struct {
int b;
};
derived_struct11 thread;
std::vector<derived_struct11> threads;
void fn () {
printf();
}
};
derived2
также происходит от base
и имеет те же два члена (thread
а также threads
) но другого типа.
class derived2 : public base {
struct derived_struct22 : public base_struct {
int c;
};
derived_struct22 thread;
std::vector<derived_struct22> threads;
void fn () {
printf();
}
};
Я могу знать, только во время выполнения derived1
или же derived2
должен быть использован. Я сделал это следующим образом:
base base_obj;
derived1 derived1_obj;
derived2 derived2_obj;
base *ptr ;
Во время выполнения функции:
{
if (condition == yes)
ptr = &derived1_obj;
else
ptr = &derived2_obj;
}
Проблема в том, что я могу получить доступ к функциям this
указатель. Но значение потоков (например: threads.size()
всегда отображается как base
учебный класс.
Я хочу знать, какой-то лучший способ реализовать это.
2 ответа
Прямая проблема заключается в том, что члены данных не могут быть виртуальными, поэтому вы не можете переопределить threads
в производных классах. Одним из решений может быть только один threads
в базовом классе, и хранить все экземпляры структуры там.
Однако тогда вы столкнетесь с проблемой нарезки: вы сохраняете объекты по значениям в std::vector<base_struct>
, Это означает, что всякий раз, когда вы помещаете объект в него, он копируется в вектор, используя (сгенерированный) конструктор копирования base_struct
, Это означает, что производная часть исходного объекта будет вырезана, и вы получите только base_struct
элемент.
Чтобы включить полиморфизм, вы должны хранить только указатели на base_struct
в вашем векторе:
std::vector<base_struct*> threads;
Другим способом было бы предоставить виртуальный добытчик для threads
, который затем можно переопределить в производных классах, чтобы вернуть желаемую коллекцию. Однако иметь несколько членов данных с одинаковыми именами в иерархии классов - это не очень хорошая идея. Это может запутать людей и привести к тонким ошибкам. Поэтому я бы предпочел первое решение, если только нет веской причины хранить отдельную коллекцию в каждом классе.
Обходной путь будет
base_struct* thread;
std::vector<base_struct*> threads; // <- hmmmmmmm
Затем в ваших производных классах установите базовые члены соответствующим образом (вместо того, чтобы определять два новых члена в производном классе - что, я думаю, совсем не то, что вы ищете)