🕵️
Введение в паттерны
  • Введение в паттерны
  • Паттерны
    • Оглавление
    • Порождающие паттерны
      • Фабричный метод
        • Реализации на С++
        • Реализации на Kotlin
        • Возможные реализации для решения конкретных задач на С++
      • Абстрактная фабрика
        • Реализации на С++
        • Реализации на Kotlin
        • Возможные реализации для решения конкретных задач на С++
      • Прототип
        • Реализации на С++
        • Реализации на Kotlin
        • Реализации на Java
        • Возможные реализации для решения конкретных задач на С++
      • Строитель
        • Реализации на С++
        • Реализации на Kotlin
      • Одиночка
        • Реализации на C++
        • Реализации на Kotlin
        • Возможные реализации для решения конкретных задач на С++
      • Пул объектов
        • Реализации на С++
    • Структурные паттерны
      • Адаптер
        • Реализации на С++
        • Реализации на Kotlin
        • Возможные реализации для решения конкретных задач
      • Декоратор
        • Реализации на С++
        • Реализации на Kotlin
      • Компоновщик
        • Реализации на С++
      • Мост
        • Реализации на С++
      • Заместитель
        • Реализации на С++
        • Реализации на Kotlin
      • Фасад
        • Реализации на С++
      • Приспособленец
        • Реализации на С++
    • Поведенческие паттерны
      • Стратегия
        • Реализации на С++
        • Реализации на Kotlin
      • Команда
        • Реализации на С++
        • Реализации на Kotlin
      • Цепочка обязанностей
        • Реализации на С++
        • Реализации на Kotlin
      • Подписчик-издатель
        • Реализации на С++
        • Реализации на Kotlin
      • Посетитель
        • Реализации на С++
        • Возможные реализации для решения конкретных задач
      • Посредник
        • Реализации на С++
        • Реализации на Kotlin
      • Шаблонный метод
        • Реализации на С++
      • Опекун
        • Реализации на С++
      • Итератор
        • Реализации на С++
        • Реализации на Kotlin
      • Свойство
        • Реализации на С++
        • Возможные реализации для решения конкретных задач
  • Введение в идиомы
  • Идиомы
    • Оглавление
    • RAII
    • Type erasure
      • Контейнеры с type erasure
    • CRTP
    • Статический полиморфизм
    • Shrink to fit
    • Proxy
    • Erase remove
    • Decltype (auto)
    • Copy and swap
    • Safe bool
    • Scope guard
    • Addressof
Powered by GitBook
On this page
  • Прототип. Идиома NVI (Non-Virtual Interface)
  • Прототип (Prototype). «Статический полиморфизм» (CRTP)
  • Прототип (Prototype). «Статический полиморфизм» (CRTP) и множественное наследование
  • Прототип (Prototype). Ковариантный виртуальный метод. Идиомы CRTP и NVI

Was this helpful?

  1. Паттерны
  2. Порождающие паттерны
  3. Прототип

Возможные реализации для решения конкретных задач на С++

Прототип. Идиома NVI (Non-Virtual Interface)

class Car
{
public:
	virtual ~Car() = default;
	unique_ptr<Car> clone();

private:
	virtual unique_ptr<Car> doClone() = 0;
};
class Sedan : public Car
{
public:
	Sedan() 
	{ 
		cout << "Calling the default constructor;" << endl; 
	}
	
	Sedan(const Sedan& car) 
	{ 
		cout << "Calling the Copy constructor;" << endl; 
	}
	
	~Sedan() override 
	{ 
		cout << "Calling the destructor;" << endl; 
	}

private:
	unique_ptr<Car> doClone() override
	{
		return make_unique<Sedan>(*this);
	}
};
class LuxurySedan : public Sedan { };

unique_ptr<Car> Car::clone()
{
	unique_ptr<Car> carClone = doClone();

	if (typeid(*carClone) != typeid(*this)) throw runtime_error("Error clone!");
	
	return carClone;
}
class User
{
public:
	void use(shared_ptr<Car> &car)
	{
		auto newCar = car->clone();
	}
};
# include <iostream>
# include <memory>
# include <exception>

using namespace std;

int main()
{
	try
	{
		shared_ptr<Car> luxsedan = make_shared<LuxurySedan>();
		User{}.use(luxsedan);
	}
	catch (exception& err)
	{
		cout << err.what() << endl;
	}
}

Прототип (Prototype). «Статический полиморфизм» (CRTP)

class Base
{
public:
    virtual ~Base() = default;

    virtual unique_ptr<Base> clone() const = 0;
    virtual ostream& print(ostream& os) const = 0;
};
template <typename Type>
concept Abstract = is_abstract_v<Type>;

template <Abstract Base, typename Derived>
class Cloner : public Base
{
public:
    unique_ptr<Base> clone() const override
    {
        return make_unique<Derived>(static_cast<const Derived&>(*this));
    }
};

// Cloner C++23
template <typename Base>
struct Cloner : public Base
{
    template <typename Self>
    unique_ptr<Base> clone(this Selt&& self) const override
    {
        return unique_ptr<Base>(new Self(self));
    }
};
class Car : public Cloner<Base, Car>
{
private:
    int serialNum;

public:
    Car(int d) : serialNum(d) 
    { 
        cout << "Calling the constructor;" << endl; 
    }
    
    Car(const Car& car) : serialNum(car.serialNum)
    {
        cout << "Calling the Copy constructor;" << endl;
    }
    
    ~Car() override 
    { 
        cout << "Calling the destructor;" << endl; 
    }

    ostream& print(ostream& os) const override
    {
        return os << "serialNum = " << serialNum;
    }
};

// Car in C++23
class Car : public Cloner<Base>
{
private:
    int serialNum;

public:
    Car(int d) : serialNum(d) {}

    ostream& print(ostream& os) const override
    {
        return os << "serialNum = " << serialNum;
    }
};
ostream& operator <<(ostream& os, const unique_ptr<Base>& obj)
{
    return obj->print(os);
}

class User
{
public:
    void use(unique_ptr<Base>& vehicle)
    {
        auto newVehicle = vehicle->clone();

        cout << newVehicle << endl;
    }
};
# include <iostream>
# include <memory>
# include <concepts>

using namespace std;

int main()
{
    unique_ptr<Base> vehicle = make_unique<Car>(10);
    User{}.use(vehicle);
}

Прототип (Prototype). «Статический полиморфизм» (CRTP) и множественное наследование

class Base
{
public:
    virtual ~Base() = default;

    unique_ptr<Base> clone() const;
    virtual ostream& print(ostream& os) const = 0;
};


unique_ptr<Base> Base::clone() const
{
    return dynamic_cast<const BaseCloner*>(this)->doClone();
}


ostream& operator <<(ostream& os, const unique_ptr<Base>& obj)
{
    return obj->print(os);
}
class BaseCloner
{
public:
    virtual unique_ptr<Base> doClone() const = 0;
};
template <typename Derived>
class Cloner : public BaseCloner
{
public:
    unique_ptr<Base> doClone() const override
    {
        return make_unique<Derived>(static_cast<const Derived&>(*this));
    }
};
class Car : public Base, public Cloner<Car>
{
private:
    int serialNum;

public:
    Car(int d) : serialNum(d) 
    { 
        cout << "Calling the constructor;" << endl; 
    }
    
    Car(const Car& car) : serialNum(car.serialNum)
    {
        cout << "Calling the Copy constructor;" << endl;
    }
    
    ~Car() override 
    { 
        cout << "Calling the destructor;" << endl; 
    }

    ostream& print(ostream& os) const override
    {
        return os << "serialNum = " << serialNum;
    }
};
class User
{
public:
    void use(unique_ptr<Base>& vehicle)
    {
        auto newVehicle = vehicle->clone();

        cout << newVehicle << endl;
    }
};
# include <iostream>
# include <memory>
# include <concepts>

using namespace std;

int main()
{
    unique_ptr<Base> vehicle = make_unique<Car>(10);
    User{}.use(vehicle);
}

Прототип (Prototype). Ковариантный виртуальный метод. Идиомы CRTP и NVI

struct NullType { };

template<typename Derived, typename Base = NullType>
struct Cloner : public Base
{
    virtual ~Cloner() = default;

    unique_ptr<Derived> clone() const
    {
        return unique_ptr<Derived>(static_cast<Derived*>(this->doClone()));
    }

protected:
    virtual Cloner* doClone() const
    {
        return new Derived(*static_cast<const Derived*>(this));
    }
};
class Car : public Cloner<Car>
{
public:
    Car() 
    { 
        cout << "Calling the car default constructor;" << endl; 
    }
    
    Car(const Car& car) 
    { 
        cout << "Calling the car Copy constructor;" << endl; 
    }

    ~Car() override 
    { 
        cout << "Calling the car destructor;" << endl; 
    }

    virtual ostream& print(ostream& os) const
    {
        return os << "Car";
    }
};

class Sedan : public Cloner<Sedan, Car>
{
public:
    Sedan() 
    { 
        cout << "Calling the sedan default constructor;" << endl; 
    }
    
    Sedan(const Sedan& car) 
    { 
        cout << "Calling the sedan Copy constructor;" << endl; 
    }

    ~Sedan() override 
    { 
        cout << "Calling the sedan destructor;" << endl; 
    }

    ostream& print(ostream& os) const override
    {
        return os << "Sedan";
    }
};
ostream& operator <<(ostream& os, const unique_ptr<Car>& vehicle)
{
    return vehicle->print(os);
}

class User
{
public:
    void use(unique_ptr<Car>& vehicle)
    {
        auto newVehicle = vehicle->clone();

        cout << newVehicle << endl;
    }
};
# include <iostream>
# include <memory>

using namespace std;

int main()
{
    unique_ptr<Car> vehicle = make_unique<Sedan>();

    User{}.use(vehicle);
}
PreviousРеализации на JavaNextСтроитель

Last updated 1 year ago

Was this helpful?