Заставить виртуальный класс использовать базовый класс другого класса - PullRequest
1 голос
/ 07 мая 2019

В настоящее время я пытаюсь построить иерархию классов, которая использует множественное наследование. У меня есть классы A, B, C и D, связанные так:

struct A
{
    int a;
    A(int a_) : a(a_) {}
};

struct B : virtual A
{
    int b;
    B(int a_, int b_) : A(a_), b(b_) {}
};

struct C : virtual A
{
    C(int a_) : A(a_) {}
};

struct D : B , C
{
    D(int a_, int b_) : A(a_), B(a_, b_) , C(a_) {}
};

Моя проблема в том, что D передает аргументы B и C, которые не нужны, и я хотел бы найти лучший способ сделать это.

Лучший способ, который я нашел, - это D инициализировать B сначала с B(a_, b_), а затем B инициализировать A с A(a_), а затем я бы инициализировал C с C(a_) (хотя аргумент не имеет значения) и 'link' C экземпляр A к B A экземпляр.

Под этим я подразумеваю, что схема памяти D будет выглядеть примерно так:

Memory Layout

Где базовый класс C A будет находиться внутри B.

Я пробовал несколько способов сделать это в C ++, но я не нашел такого, где он позволил бы мне изменить местоположение C A, и при этом я не знаю, возможно ли это.

Мой вопрос: возможно ли достичь этого в C ++, используя наследование или, возможно, другой инструмент?


Даже если бы это было возможно, у меня все равно была бы проблема инициализации как B, так и C с помощью аргумента 'dummy', который ничего не делал, это хорошо для int, но не для чего-то более «тяжелый».

Я бы хотел, чтобы при наследовании от B или C вы использовали пустой конструктор для его инициализации и использовали другой конструктор при его обычном создании, что-то вроде этого:

struct A
{
    int a;
    A(int a_) : a(a_) {}
};

struct B : virtual A
{
    int b;
    B(int a_, int b_) : A(a_), b(b_) {}

    protected:

    // The A initialization will never get called
    B(int b_) : A(0), b(b_) {}
};

struct C : virtual A
{
    C(int a_) : A(a_) {}

    protected:

    // This initialization will never get called
    C() : A(0) {}
};

struct D : B , C
{
    D(int a_, int b_) : A(a_), B(b_) , C() {}
};

Единственная проблема в том, что я не уверен, что у этого есть какие-либо побочные эффекты, о которых я должен знать, или, если это даже работает, я не мог придумать, как это проверить хорошо.

Я не уверен, приемлемо ли задавать два вопроса в одном, я считаю, что они имеют смысл вместе, но если нет, я отредактирую его и задам как другой вопрос.

Редактировать 1:

В отношении дубликата этот ответ гласит, что неиспользуемые аргументы не будут использоваться для инициализации самого базового класса в двух производных классах.

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

Таким образом, более конкретно, мой второй вопрос Является ли эта реализация предотвращения предоставления параметров двум производным классам хорошей или есть какие-либо побочные эффекты, которые я не учел при создании?

...