Иерархия классов, преобразовать указатель на объект D1 в D2 (множественное наследие)

Здравствуйте! Вот я столкнулся с задачей на с++, я сам не могу пока ее решить, прошу Вас, разъясните эту задачу и дайте полное её решение вместе с программой.

Заранее Вас благодарю.

Вот, сама задача:

Вам дана следующая иерархия классов:

struct Base { ... };  

struct D1 : Base { ... }; 

struct D2 : Base { ... };  

struct D3 : D1, D2 { ... };

Напишите функцию D1BaseToD2Base, которая преобразует указатель типа Base на объект типа D3, который ссылается на экземпляр Base, соответствующий D1, в указатель, ссылающийся на экземпляр Base соответствующий D2.

Указание: не забывайте про константность!

Напишите программу:

// base указывает на экземпляр Base, соответствующий D1 

// нужно вернуть указатель на экземпляр Base, соответствующий D2 

Base const * D1BaseToD2Base( Base const * base ) 

{ 


    return ... 

}

А вы что делать будете?))

Что именно непонятно? Что пробовали делать, что читали?

Тут цель задачи видимо в том, чтобы изучить глубже множественное наследование и приведение типов.

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

И потом погуглить c++ multiple inheritance cast и вроде бы даже найти почти решение:
https://stackoverflow.com/questions/7426422/multiple-inheritance-casting-from-base-class-to-different-derived-class
(либо dynamic_cast, либо скастовать сначала к D3, а потом к D2)

У Вас задача на наследование через инстацирование.
Заводим переключатель.

const soReference=1;
const soOwned=0;
typedef TBaseOwnership = int;

и заводим переменную Base.ownership по которой будем определять у нас экземляр Base или указатель. Внутри Base скрытую ссылку на base.
Если ownership==soReference, то все гетеры и сеторы обращаются через ссылку this.base.
Если ownership==soOwned, то все гетеры и сеторы обращаются к полям класса.

Base const * D1BaseToD2Base( Base const * base )
{
D3 *d3=(D3 *)(base.parent); // Будем изменять на месте, а не создавая новый объект.   
D2 *d2=new D2(this, d3.d1.base, soReference); // инстанцируем  в указатель, ссылающийся на экземпляр Base
if (d3.d1.base.ownership==soOwned){
//d3.d1.base.parent=d2; // Говорим что объект теперь в коллекции d2.
// Так поступить мы не можем так как объект у нас константный
// Можно сделать так 
d3.d1.base.setParent(d2);
} else {
  delete d3.d1.Base; 
}
d3.d1=nil; 
return d3.base;
}

Конструктор

Base* Base(void* parent; Base* aBase; Owenship aOwenship)
{
this.parent=aParent;
if (aOwenship==soReference) {
this.base=aBase;
} else {
this.value=aBase.value; // инстанцируем(отпочковываем) при помощи копирования значения полей.
}
}

Код набирал прямо здесь могут быть ошибки.

В С++ это вроде бы решается без этого.

Там же

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

https://ru.wikipedia.org/wiki/Ромбовидное_наследование


В целом задача выглядит как то, чего надо избегать в реальной жизни :catshake:
Но польза от нее в получении более глубокого понимания С++.

Да посмотрел. Через dynamic_cast там проще делается. Так как уже всё реализовано внутри.

dynamic_cast<D3>(base).d2=dynamic_cast<D2>(dynamic_cast<Base>(dynamic_cast<D3>(base).d1));
dynamic_cast<D3>(base).d1=nil;

Сообщение было перенесено в новую тему: Реализуйте функцию array_size, которая возвращает размер массива