Рубрики

Продвинутый C ++ | Конструктор виртуальных копий

В идиоме виртуального конструктора мы видели способ создания объекта, тип которого не определен до времени выполнения. Можно ли создать объект, не зная его точного типа класса? Конструктор виртуальной копии решает этот вопрос.

Иногда нам может понадобиться построить объект из другого существующего объекта. Точно так же конструктор копирования делает то же самое. Начальное состояние нового объекта будет основано на другом существующем состоянии объекта. Компилятор вызывает вызов конструктора копирования, когда объект создается из другого объекта. Однако компилятору нужна конкретная информация о типе для вызова соответствующего конструктора копирования.

#include <iostream>

using namespace std;

  

class Base

{

public:

    //

};

  

class Derived : public Base

{

public:

    Derived()

    {

        cout << "Derived created" << endl;

    }

  

    Derived(const Derived &rhs)

    {

        cout << "Derived created by deep copy" << endl;

    }

  

    ~Derived()

    {

        cout << "Derived destroyed" << endl;

    }

};

  

int main()

{

    Derived s1;

  

    Derived s2 = s1;  // Компилятор вызывает "конструктор копирования"

                      // Типы s1 и s2 являются конкретными для компилятора

  

    // Как мы можем создать объект Derived1 или Derived2

    // из указателя (ссылки) в базовый класс, указывающий на производный объект?

  

    return 0;

}

Что делать, если мы не можем решить, из какого типа объекта будет создана копия? Например, виртуальный конструктор создает объект иерархии классов во время выполнения на основе некоторого ввода. Когда мы хотим скопировать конструкцию объекта из другого объекта, созданного виртуальным конструктором, мы не можем использовать обычный конструктор копирования. Нам нужна специальная функция клонирования, которая может дублировать объект во время выполнения.

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

Точно так же рассмотрим приложение с буфером обмена. Буфер обмена может содержать различные типы объектов и копировать объекты из существующих объектов, вставляя их на холст приложения. Опять же, какой тип объекта должен быть скопирован — это решение во время выполнения. Конструктор виртуальных копий заполняет пробел здесь. Смотрите пример ниже,

#include <iostream>

using namespace std;

  
//// БИБЛИОТЕКА SRART

class Base

{

public:

    Base() { }

  

    virtual // Гарантирует вызов фактического деструктора объекта

        ~Base() { }

  

    virtual void ChangeAttributes() = 0;

  

    // Виртуальный конструктор

    static Base *Create(int id);

  

    // Конструктор виртуальных копий

    virtual Base *Clone() = 0;

};

  

class Derived1 : public Base

{

public:

    Derived1()

    {

        cout << "Derived1 created" << endl;

    }

  

    Derived1(const Derived1& rhs)

    {

        cout << "Derived1 created by deep copy" << endl;

    }

  

    ~Derived1()

    {

        cout << "~Derived1 destroyed" << endl;

    }

  

    void ChangeAttributes()

    {

        cout << "Derived1 Attributes Changed" << endl;

    }

  

    Base *Clone()

    {

        return new Derived1(*this);

    }

};

  

class Derived2 : public Base

{

public:

    Derived2()

    {

        cout << "Derived2 created" << endl;

    }

  

    Derived2(const Derived2& rhs)

    {

        cout << "Derived2 created by deep copy" << endl;

    }

  

    ~Derived2()

    {

        cout << "~Derived2 destroyed" << endl;

    }

  

    void ChangeAttributes()

    {

        cout << "Derived2 Attributes Changed" << endl;

    }

  

    Base *Clone()

    {

        return new Derived2(*this);

    }

};

  

class Derived3 : public Base

{

public:

    Derived3()

    {

        cout << "Derived3 created" << endl;

    }

  

    Derived3(const Derived3& rhs)

    {

        cout << "Derived3 created by deep copy" << endl;

    }

  

    ~Derived3()

    {

        cout << "~Derived3 destroyed" << endl;

    }

  

    void ChangeAttributes()

    {

        cout << "Derived3 Attributes Changed" << endl;

    }

  

    Base *Clone()

    {

        return new Derived3(*this);

    }

};

  
// Мы также можем объявить «Create» вне Base.
// Но более уместно ограничить его область действия Base

Base *Base::Create(int id)

{

    // Просто расширяем лестницу if-else, если создан новый производный класс

    // Пользователь не должен быть перекомпилирован для создания вновь добавленных объектов класса

  

    if( id == 1 )

    {

        return new Derived1;

    }

    else if( id == 2 )

    {

        return new Derived2;

    }

    else

    {

        return new Derived3;

    }

}
//// КОНЕЦ БИБЛИОТЕКИ

  
//// Утилита SRART

class User

{

public:

    User() : pBase(0)

    {

        // Создает любой объект Base heirarchey во время выполнения

  

        int input;

  

        cout << "Enter ID (1, 2 or 3): ";

        cin >> input;

  

        while( (input !=  1) && (input !=  2) && (input !=  3) )

        {

            cout << "Enter ID (1, 2 or 3 only): ";

            cin >> input;

        }

  

        // Создание объектов через «Виртуальный конструктор»

        pBase = Base::Create(input);

    }

  

    ~User()

    {

        if( pBase )

        {

            delete pBase;

            pBase = 0;

        }

    }

  

    void Action()

    {

        // дублировать текущий объект

        Base *pNewBase = pBase->Clone();

  

        // Изменить его атрибуты

        pNewBase->ChangeAttributes();

  

        // Удалить созданный объект

        delete pNewBase;

    }

  

private:

    Base *pBase;

};

  
//// конец утилиты

  
//// Потребительский класс пользователя (UTILITY)

int main()

{

    User *user = new User();

  

    user->Action();

  

    delete user;

}

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

Венки . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Продвинутый C ++ | Конструктор виртуальных копий

0.00 (0%) 0 votes