Полиморфизм времени выполнения с указателями в 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

Затем в ваших производных классах установите базовые члены соответствующим образом (вместо того, чтобы определять два новых члена в производном классе - что, я думаю, совсем не то, что вы ищете)

Другие вопросы по тегам