Композитный с умными указателями без dynamic_pointer_cast

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

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

Я хочу знать, возможно ли это сделать без использования dynamic_pointer_cast,

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

#include <iostream>
#include <vector>
#include <memory>

class Fruit
{
public:
virtual void getOld() = 0;
};

class Orange : Fruit
{
public:
Orange() {}

void add(std::shared_ptr<Fruit> f)
{
v.push_back(f);
}

std::shared_ptr<Fruit> get(int k)
{
return v[k];
}

void getOld()
{
std::cout << "Orange - I'm old." << std::endl;
}
private:
std::vector<std::shared_ptr<Fruit>> v;
};

class Bitter : public Fruit
{
public:
Bitter() {}

void getOld()
{
std::cout << "Bitter - I'm old." << std::endl;
}

void getNew()
{
std::cout << "Bitter - I'm new." << std::endl;
}
};

int main(int argc, char ** argv)
{
auto orange = new Orange;
orange->add(std::make_shared<Bitter>());
auto bitter = orange->get(0);
bitter->getOld();

return 0;
}

Это работает, как вы можете видеть здесь на предварительный просмотр в реальном времени, но когда я пытаюсь использовать:

int main(int argc, char ** argv)
{
auto orange = new Orange;
orange->add(std::make_shared<Bitter>());
auto bitter = orange->get(0);
bitter->getOld();
bitter->getNew();

return 0;
}

Я получил ошибки:

ошибка: в классе Fruit нет члена с именем getNew

Заранее спасибо.

2

Решение

Проблема здесь, я думаю, в том, что она будет работать с полиморфизмом, но метод ‘getNew’ не существует в родительском классе, поэтому вам нужно определить его и сделать его виртуальным. Это единственный способ сделать это без использования приведения объекта.
С этой линией должно работать.

virtual void getNew() = 0;
2

Другие решения

Одним из возможных решений является наличие следующей функции в Orange,

template <typename T>
T* get(int k)
{
return dynamic_cast<T*>(v[k].get());
}

А затем используйте:

auto bitter = orange->get<Bitter>(0);
bitter->getOld();
bitter->getNew();

Это выполняет dynamic_cast но локализован на Orange,

1

Следующая информация может быть найдена о «составной шаблон» от GOF книга. Конечно, это было объяснено на основе графического класса.

ключ Составной шаблон абстрактный класс тот представляет собой и то и другое примитивы а также их контейнеры. Для графической системы этот класс — Графический. Графика объявляет операции как Рисовать которые являются специфическими для графических объектов. Это также объявляет операции, которые все составные объекты разделяют, такие как операции для доступа и управления своими дочерними элементами.

Исходя из вышеприведенного объяснения, мы должны в идеале объявлять все возможные интерфейсы листового и неконечного (контейнерного) типа узла при использовании составного шаблона. Я считаю, что это важно для того, чтобы клиент мог обрабатывать отдельные объекты и композиции объектов равномерно. Поэтому в идеале вы должны объявить свои классы следующим образом, используя этот конкретный шаблон. Любая логика, которая была написана на основе точного типа объекта в клиентском коде, нарушает суть этого шаблона.

//Abstract class which should have all the interface common to
// Composite and Leaf class. It may also provide the default
// implementation wherever appropriate.
class Fruit {
public:
virtual void getOld() = 0;
virtual void getNew() = 0;
virtual void add(std::shared_ptr<Fruit> f) { }
virtual  std::shared_ptr<Fruit> get(int index ) {return nullptr; }
virtual ~Fruit() { }
};//Composite Node
class Orange : Fruit {
public:
Orange() {}
void add(std::shared_ptr<Fruit> f) { v.push_back(f); }
std::shared_ptr<Fruit> get(int k) { return v[k]; }
void getOld()  { std::cout << "Orange - I'm old." << std::endl; }
void getNew() { std::cout << "Orange - I'm new." << std::endl; }
private:
std::vector<std::shared_ptr<Fruit>> v;
};//Leaf node
class Bitter : public Fruit {
public:
Bitter() {}
void getOld() { std::cout << "Bitter - I'm old." << std::endl; }
void getNew() { std::cout << "Bitter - I'm new." << std::endl; }
};
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector