Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.12.2012, 11:12   #11
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Проверил. Работает хорошо, но есть одно НО: созданные в наследниках данные не копируются в объект-клон.
Lasor вне форума Ответить с цитированием
Старый 13.12.2012, 12:52   #12
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Lasor Посмотреть сообщение
Проверил. Работает хорошо, но есть одно НО: созданные в наследниках данные не копируются в объект-клон.
Значит копирующий конструктор через одно место. Показывай код.
_Bers вне форума Ответить с цитированием
Старый 13.12.2012, 13:48   #13
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Значит копирующий конструктор через одно место. Показывай код.
Дело в том, что написать универсальный конструктор копирования не представляется возможным, ибо я не могу узнать, каких наследников и с какими методами/членами будут создавать пользователи/разработчики.
Есть ли способ это обойти?
Lasor вне форума Ответить с цитированием
Старый 13.12.2012, 13:59   #14
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Lasor Посмотреть сообщение
Дело в том, что написать универсальный конструктор копирования не представляется возможным, ибо я не могу узнать, каких наследников и с какими методами/членами будут создавать пользователи/разработчики.
Есть ли способ это обойти?

Ты не понял. Не нужен никакой универсальный копирующий конструктор.
Более того, конструкторы - это собственность конкретных классов. Конструкторы конструируют объекты только своего собственного класс, и ни за какие другие классы они не отвечают.

Тебе нужно немножко прокачать скилл по теме "полиморфизм".

Вот смотри:
http://ideone.com/YQhsm4

Код:
#include<iostream>
#include<vector>
 
    struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        Concrete_Object1(){ std::cout<<"Concrete_Object1: was build\n";  }
        Concrete_Object1(const Concrete_Object1& rhs) { std::cout<<"Concrete_Object1: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
    struct Concrete_Object2: IObject
    {
        Concrete_Object2(){ std::cout<<"Concrete_Object2: was build\n";  }
        Concrete_Object2(const Concrete_Object2& rhs) { std::cout<<"Concrete_Object2: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object2: working\n";    }
        virtual ~Concrete_Object2()       { std::cout<<"Concrete_Object2: destroyed\n";  }
        virtual Concrete_Object2* Clone() { return new Concrete_Object2(*this);          }
    };    
        
    struct Manager
    {
        ~Manager()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ delete mObj[n]; mObj[n] = 0l; }
        }
        
        void Connect(IObject* src){  mObj.push_back( src->Clone() ); }
        
        void Work()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ mObj[n]->Work(); }
        }
        std::vector<IObject*> mObj;
    };
 
 
int main()
{
   Manager man;
   IObject* agent1 = new Concrete_Object1();
   IObject* agent2 = new Concrete_Object2();
   
   man.Connect(agent1);
   man.Connect(agent2);
   
   delete agent1;
   delete agent2;
   
   man.Work();
   
   return 0;
}
Вывод в консоль:
Код:
Concrete_Object1: was build
Concrete_Object2: was build
Concrete_Object1: was build by copy
Concrete_Object2: was build by copy
Concrete_Object1: destroyed
Concrete_Object2: destroyed
Concrete_Object1: working
Concrete_Object2: working
Concrete_Object1: destroyed
Concrete_Object2: destroyed
Здесь менеджер не знает, с каким фактическим типом объектов он имеет дело. Он работает только через интерфейс.

По интерфейсу он запрашивает копию объекта.

Рассмотрим это более подробно:

Код:
struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        Concrete_Object1(){ std::cout<<"Concrete_Object1: was build\n";  }
        Concrete_Object1(const Concrete_Object1& rhs) { std::cout<<"Concrete_Object1: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
Метод IObject::Clone() запустит метод наследника Concrete_Object1::Clone()

Внутри которого происходит процедура создания нового объекта в динамической памяти:

Код:
return new Concrete_Object1(*this);
Здесь: Concrete_Object1(*this); это запуск копирующего конструктора, аргументом которого является объект, запустивший этот конструктор.

То бишь, запустится метод: Concrete_Object1(const Concrete_Object1& rhs)

Конкретный объект знает собственное устройство, и поэтому знает как построить себе подобного.
_Bers вне форума Ответить с цитированием
Старый 13.12.2012, 15:52   #15
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Ты не понял. Не нужен никакой универсальный копирующий конструктор.
Более того, конструкторы - это собственность конкретных классов. Конструкторы конструируют объекты только своего собственного класс, и ни за какие другие классы они не отвечают.

Тебе нужно немножко прокачать скилл по теме "полиморфизм".

Вот смотри:
http://ideone.com/YQhsm4

Код:
#include<iostream>
#include<vector>
 
    struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        Concrete_Object1(){ std::cout<<"Concrete_Object1: was build\n";  }
        Concrete_Object1(const Concrete_Object1& rhs) { std::cout<<"Concrete_Object1: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
    struct Concrete_Object2: IObject
    {
        Concrete_Object2(){ std::cout<<"Concrete_Object2: was build\n";  }
        Concrete_Object2(const Concrete_Object2& rhs) { std::cout<<"Concrete_Object2: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object2: working\n";    }
        virtual ~Concrete_Object2()       { std::cout<<"Concrete_Object2: destroyed\n";  }
        virtual Concrete_Object2* Clone() { return new Concrete_Object2(*this);          }
    };    
        
    struct Manager
    {
        ~Manager()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ delete mObj[n]; mObj[n] = 0l; }
        }
        
        void Connect(IObject* src){  mObj.push_back( src->Clone() ); }
        
        void Work()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ mObj[n]->Work(); }
        }
        std::vector<IObject*> mObj;
    };
 
 
int main()
{
   Manager man;
   IObject* agent1 = new Concrete_Object1();
   IObject* agent2 = new Concrete_Object2();
   
   man.Connect(agent1);
   man.Connect(agent2);
   
   delete agent1;
   delete agent2;
   
   man.Work();
   
   return 0;
}
Вывод в консоль:
Код:
Concrete_Object1: was build
Concrete_Object2: was build
Concrete_Object1: was build by copy
Concrete_Object2: was build by copy
Concrete_Object1: destroyed
Concrete_Object2: destroyed
Concrete_Object1: working
Concrete_Object2: working
Concrete_Object1: destroyed
Concrete_Object2: destroyed
Здесь менеджер не знает, с каким фактическим типом объектов он имеет дело. Он работает только через интерфейс.

По интерфейсу он запрашивает копию объекта.

Рассмотрим это более подробно:

Код:
struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        Concrete_Object1(){ std::cout<<"Concrete_Object1: was build\n";  }
        Concrete_Object1(const Concrete_Object1& rhs) { std::cout<<"Concrete_Object1: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
Метод IObject::Clone() запустит метод наследника Concrete_Object1::Clone()

Внутри которого происходит процедура создания нового объекта в динамической памяти:

Код:
return new Concrete_Object1(*this);
Здесь: Concrete_Object1(*this); это запуск копирующего конструктора, аргументом которого является объект, запустивший этот конструктор.

То бишь, запустится метод: Concrete_Object1(const Concrete_Object1& rhs)

Конкретный объект знает собственное устройство, и поэтому знает как построить себе подобного.
Эти утверждения верны, но дело в том, что у меня Concrete_Object является шаблонным классом. От него-то и наследуются "наследники", которые должны прописываться в диспетчер.
Проблема состоит в том, что из класса-родителя я не могу "достучаться" до "наследников".
Lasor вне форума Ответить с цитированием
Старый 13.12.2012, 16:23   #16
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

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

Код:
#include<typeinfo>
#include<iostream>
#include<vector>
 
 
    struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    template<class T>struct Template_Object: IObject
    {
        Template_Object()
        {
            std::cout<<"TObject: was build with type: "<<typeid(T).name()<<'\n';
        }
        Template_Object(const Template_Object& rhs) 
        {
            std::cout<<"TObject: was build by copy, with type: "<<typeid(T).name()<<'\n'; 
        }
        virtual void Work()               
        {
            std::cout<<"TObject: working, with type: "<<typeid(T).name()<<'\n'; 
        }
        virtual ~Template_Object()       
        {
            std::cout<<"TObject: destroyed, with type: "<<typeid(T).name()<<'\n'; 
        }
        virtual Template_Object* Clone() { return new Template_Object(*this);  }
    };
    
    struct Concrete_Object2: IObject
    {
        Concrete_Object2(){ std::cout<<"Concrete_Object2: was build\n";  }
        Concrete_Object2(const Concrete_Object2& rhs) { std::cout<<"Concrete_Object2: was build by copy\n";  }
        virtual void Work()               { std::cout<<"Concrete_Object2: working\n";    }
        virtual ~Concrete_Object2()       { std::cout<<"Concrete_Object2: destroyed\n";  }
        virtual Concrete_Object2* Clone() { return new Concrete_Object2(*this);          }
    };    
        
    struct Manager
    {
        ~Manager()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ delete mObj[n]; mObj[n] = 0l; }
        }
        
        void Connect(IObject* src){  mObj.push_back( src->Clone() ); }
        
        void Work()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ mObj[n]->Work(); }
        }
        std::vector<IObject*> mObj;
    };
 
 
int main()
{
   Manager man;
   IObject* agent1 = new Template_Object<int>();
   IObject* agent2 = new Template_Object<float>();
   IObject* agent3 = new Concrete_Object2();
   
   man.Connect(agent1);
   man.Connect(agent2);
   man.Connect(agent3);
   
   delete agent1;
   delete agent2;
   delete agent3;
   
   man.Work();
   
   return 0;
}
вывод в консоль:

Код:
TObject: was build with type: i
TObject: was build with type: f
Concrete_Object2: was build
TObject: was build by copy, with type: i
TObject: was build by copy, with type: f
Concrete_Object2: was build by copy
TObject: destroyed, with type: i
TObject: destroyed, with type: f
Concrete_Object2: destroyed
TObject: working, with type: i
TObject: working, with type: f
Concrete_Object2: working
TObject: destroyed, with type: i
TObject: destroyed, with type: f
Concrete_Object2: destroyed
_Bers вне форума Ответить с цитированием
Старый 14.12.2012, 10:42   #17
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Код:
//----------------------------------
//Базовый
//----------------------------------
class V
{
public:
    V(){}
    ~V(){}
    virtual string getName() = 0;
    virtual void notify() = 0;
    virtual void handle() = 0;
};
//----------------------------------
//Наследник
//----------------------------------
template <class T>
class E: public V
{
public:
    E(const E& src);
    string getName();
    void notify();
    void handle();
};
//----------------------------------
//Отдельный
//----------------------------------
class B
{
public:
    B(){}
    void add(V *e)
    {
        tempName = e->getName();
        eList.push_back(e);
    }
    void go()
    {
        for (short i = 0; i < (short)evList.size(); i++)
        {
            eList[i]->handle();
        }
    }
private:
    string tempName;
    static vector <V*> eList;
};
//----------------------------------
//Создаю наследника от шаблонного наследника базового
//----------------------------------
Class E_1: public E<E_1>
{
public:
E_1(){}
E_1(const E_1& src)
{
    this someint = src.someint;
}
    int someint;
}
Так вот после его создания и вызова B.add(&E_1); элемент добавляется в очередь менеджера. Однако, получив доступ к элементам имею не инициализированные члены...
Lasor вне форума Ответить с цитированием
Старый 16.12.2012, 00:36   #18
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Код:
//----------------------------------
//БаAзовый
//----------------------------------
class V
{
public:
    V(){}
    ~V(){}
    virtual string getName() = 0;
    virtual void notify() = 0;
    virtual void handle() = 0;
};
//----------------------------------
//Наследник
//----------------------------------
template <class T>
class E: public V
{
public:
    E(const E& src);
    string getName();
    void notify();
    void handle();
    virtual E* clone()
    {
        return new E(*this);
    }
};
//----------------------------------
//Отдельный
//----------------------------------
class B
{
public:
    B(){}
    void add(V *e)
    {
        tempName = e->getName();
        eList.push_back(e->clone());
    }
    void go()
    {
        for (short i = 0; i < (short)evList.size(); i++)
        {
            eList[i]->handle();
        }
    }
private:
    string tempName;
    static vector <V*> eList;
};
//----------------------------------
//Создаю наследника от шаблонного наследника базового
//----------------------------------
Class E_1: public E<E_1>
{
public:
E_1(){}
E_1(const E_1& src)
{
    this someint = src.someint;
}
    int someint;
}
Вноват, вот так делаю... И не вызывается конструктор копирования у наследников шаблонного класса...
Lasor вне форума Ответить с цитированием
Старый 16.12.2012, 00:40   #19
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Код:
Class E_1: public E<E_1>
{
public:
E_1(){}
E_1(const E_1& src)
{
    this someint = src.someint;  //<--- это что?
}
    int someint;
}
У меня такое даже и не компилируется.
Может быть ты имел ввиду:

Код:
E_1(const E_1& src){    this->someint = src.someint;  }
или:

Код:
E_1(const E_1& src){   someint = src.someint;  }
_Bers вне форума Ответить с цитированием
Старый 16.12.2012, 13:44   #20
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Код:
Class E_1: public E<E_1>
{
public:
E_1(){}
E_1(const E_1& src)
{
    this someint = src.someint;  //<--- это что?
}
    int someint;
}
У меня такое даже и не компилируется.
Может быть ты имел ввиду:

Код:
E_1(const E_1& src){    this->someint = src.someint;  }
или:

Код:
E_1(const E_1& src){   someint = src.someint;  }
Прошу прощения. Я имел ввиду:
Код:
Class E_1: public E<E_1>
{
public:
E_1(){}
E_1(const E_1& src)
{
    this->someint = src.someint;  //<--- это что?
}
    int someint;
}
Опечатался...
Lasor вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание экземпляра класса biohazard120 Общие вопросы Delphi 11 15.09.2012 13:23
C#(перехват нового экземпляра класса StackOverflowException) Anett// Помощь студентам 0 12.05.2011 22:26
Освобождение памяти от экземпляра класса Mixim Общие вопросы .NET 8 05.01.2011 17:27
удаление экземпляра класса Juffin Общие вопросы Delphi 5 02.11.2010 11:57
ListBox, привязка экземпляра класса к Item. Возможно ли? Casper-SC Общие вопросы .NET 1 24.05.2010 10:40