Виртуальный конструктор
От: dipso  
Дата: 24.03.14 00:54
Оценка: :)))
Летать летает.
#include <windows.h>
#include <tchar.h>
#include <string>
#include <iostream>


struct First;

struct VCons
{

    First* first;

    VCons()
    {}

    ~VCons();
};


struct First
{
    First(VCons& vc=VCons())
    {
        vc.first = this;
    }

    virtual void Print()
    {
        std::cout<<"in First"<<std::endl;
    }

    void Init()
    {
        Print();
    }
};

struct Second : public First
{
    Second(VCons& vc=VCons()) : First(vc)
    {}

    void Print()
    {
        std::cout<<"in Second"<<std::endl;
    }
};

struct Third : public Second
{
    Third(VCons& vc=VCons()) : Second(vc)
    {}

    void Print()
    {
        std::cout<<"in Third"<<std::endl;
    }
};

VCons::~VCons()
{

    first->Print();
}

int main()
{
    Third s;

    int i=0;
    std::cin>>i;
    return 0;
}

пойдёт?
Re: Виртуальный конструктор
От: мыщъх США http://nezumi-lab.org
Дата: 24.03.14 00:58
Оценка:
Здравствуйте, dipso, Вы писали:

D>Летать летает.

оно не только не летает, но и не компилируется
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[2]: Виртуальный конструктор
От: dipso  
Дата: 24.03.14 01:05
Оценка:
Здравствуйте, мыщъх, Вы писали:

М>Здравствуйте, dipso, Вы писали:


D>>Летать летает.

М>оно не только не летает, но и не компилируется

спасибО
Re: Виртуальный конструктор
От: Abyx Россия  
Дата: 24.03.14 05:20
Оценка:
Здравствуйте, dipso, Вы писали:

D>пойдёт?

нет.
куча бойлерплейта, исключения бросать нельзя, чем лучше обычной фабрики — непонятно.
In Zen We Trust
Re: Виртуальный конструктор
От: Vain Россия google.ru
Дата: 28.03.14 09:41
Оценка:
Здравствуйте, dipso, Вы писали:

D>пойдёт?

Неа. Какой же это виртуальный конструктор, когда тип конструирования заранее известен? Вот когда добъёшься конструирования неизвестного типа вот тогда и приходи.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: Виртуальный конструктор
От: Кодт Россия  
Дата: 28.03.14 14:18
Оценка:
Здравствуйте, Vain, Вы писали:

D>>пойдёт?

V>Неа. Какой же это виртуальный конструктор, когда тип конструирования заранее известен? Вот когда добъёшься конструирования неизвестного типа вот тогда и приходи.

Вообще, вся эта каша заварена только ради двухфазной инициализации, сохраняя видимость обычного конструктора.
Вместо этого можно было бы предложить дизайн, похожий на make_shared сотоварищи
template<class T, class... Args>
unique_ptr<T>
make_initialized(Args... args)
{
  unique_ptr<T> p = make_unique<T>(args...); // конструируем
  call_init(*p, args...); // вызываем p->init(args...)
  return p;
}

template<class T, class... Args>
auto call_init(T& t, Args... args) -> typename enable_if< EXIST(t.init(args...)) >::type
{
  t.init(args...);
}
template<class T, class... Args>
auto call_init(T& t, Args... args) -> typename enable_if< EXIST(t.init()) && !EXIST(t.init(args...)) >::type
{
  t.init();
}
template<class T, class... Args>
auto call_init(T& t, Args... args) -> typename enable_if< !EXIST(t.init()) && !EXIST(t.init(args...)) >::type
{
}

// макрос EXIST напишите сами :)


Для двухфазной деструкции придётся немножко потанцевать, но тоже нет ничего невозможного.
Перекуём баги на фичи!
Re[3]: Виртуальный конструктор
От: dipso  
Дата: 29.03.14 06:30
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Вообще, вся эта каша заварена только ради двухфазной инициализации, сохраняя видимость обычного конструктора.
К>Вместо этого можно было бы предложить дизайн, похожий на make_shared сотоварищи
...
К>Для двухфазной деструкции придётся немножко потанцевать, но тоже нет ничего невозможного.

Каша заварена для того чтобы избежать двухфазную инициализацию дабы следовать идиоме RAII.
После вызова конструктора, до вызова инициализирующего метода, объект находится в подвешеном состоянии. Кто, когда и где его вызовет?
Вероятно ещё придётся ввести поле bool created и соответствующий метод, нужно решать что делать если created=false.
Тут говорили: много лишнего кода. В определении конструктора VCons vc=VCons(), передача vc в список инициализации, и наследование от Base(см.дальше).
Просто строчка в конструкторе.Инициализация как и ожидается — в виртуальном методе.
Объект виртуального конструктора исключений не кидает. Для обработки всех остальных — function-try block.
Если использовать двухфазную инициализацию — вызов дополнительного метода для каждого созданного объекта.

Проблема решается просто для объектов из кучи — переопределением operator new.
Но для стековых объектов это не подходит.

Вот ещё один вариант, для наглядности создал иерархию виджетов.

#ifdef _WIN32
#include <windows.h>
#pragma warning(disable:4355)
#endif//_WIN32

#include <string>
#include <iostream>


struct Base;
struct Widget;

struct VCons
{
    VCons() : caller(this), base(NULL), param(NULL)
    {}

    VCons(const VCons& vc) : caller(&vc), base(NULL), param(NULL)
    {}

    ~VCons();

    void Set(Base* c, Widget* p) const
    {
        base = c;
        param = p;
    }

private:

    const VCons* caller;
    mutable Base* base;
    mutable Widget* param;

};


struct Base
{
    Base(Widget* p, VCons vc)
    {
        vc.Set(this, p);
    }

    virtual void OnCreate(Widget* p)=0;
};

struct Widget : public Base
{
    Widget* parent;

    Widget(Widget* p, VCons vc=VCons()) : Base(p, vc), parent(NULL)
    {}

    void OnCreate(Widget* p)
    {
        parent = p;
    }
};

struct Button : public Widget
{
    Button(Widget* p, VCons vc=VCons()) : Widget(p, vc)
    {}

    void OnCreate(Widget* p)
    {
        Widget::OnCreate(p);
        std::cout<<"Button"<<std::endl;
    }
};

struct RadioButton : public Button
{
    RadioButton(Widget* p, VCons vc=VCons()) : Button(p, vc)
    {}

    void OnCreate(Widget* p)
    {
        Widget::OnCreate(p);
        std::cout<<"RadioButton"<<std::endl;
    }
};

struct MainFrame : public Widget
{
    Button button;
    RadioButton radio;

    MainFrame(VCons vc=VCons()) : Widget(NULL, vc), button(this), radio(this)
    {}

    void OnCreate(Widget* p)
    {        
        Widget::OnCreate(NULL);
        std::cout<<"MainFrame"<<std::endl;
    }
};

VCons::~VCons()
{
    if(caller == this)
        base->OnCreate(param);
    else
        caller->Set(base, param);
}

int main()
{
    MainFrame frame;

    int i=0;
    std::cin>>i;
    return 0;
}


В данной иерархии одна проблема — MainFrame должен быть создан раньше чем кнопки. Не пробовал, но на ум приходит использование очереди.
Re[4]: Виртуальный конструктор
От: Кодт Россия  
Дата: 29.03.14 14:04
Оценка:
Здравствуйте, dipso, Вы писали:

D>Каша заварена для того чтобы избежать двухфазную инициализацию дабы следовать идиоме RAII.

D>После вызова конструктора, до вызова инициализирующего метода, объект находится в подвешеном состоянии. Кто, когда и где его вызовет?

Как нефиг делать привычными способами
template<class T> struct oncreated : public T
{
  template<class... Args> initialized(Args... args) : T(args...) { OnCreate(); }
};

.......

oncreated<MainFrame> mf; // да хоть статическая переменная!
Перекуём баги на фичи!
Re[5]: Виртуальный конструктор
От: dipso  
Дата: 29.03.14 18:18
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, dipso, Вы писали:


D>>Каша заварена для того чтобы избежать двухфазную инициализацию дабы следовать идиоме RAII.

D>>После вызова конструктора, до вызова инициализирующего метода, объект находится в подвешеном состоянии. Кто, когда и где его вызовет?

К>Как нефиг делать привычными способами

К>
К>template<class T> struct oncreated : public T
К>{
К>  template<class... Args> initialized(Args... args) : T(args...) { OnCreate(); }
К>};

К>.......

К>oncreated<MainFrame> mf; // да хоть статическая переменная!
К>

Я Вас не понял. Тип — oncreated, конструктор — initialized. OnCreate — понятно, виртуальный. Но ведь сам T, и его предки в своём конструкторе тоже должны вызвать
OnCreate, но они пока не знают о том что им его вызывать не надо. В общем не понял я, вашу мысль. А так да, вызов в каждом конструкторе OnCreate — самое простое решение. Нужно суметь решить — вызывать его или нет. Подъясните пожалуйста.
Re[6]: Виртуальный конструктор
От: Кодт Россия  
Дата: 30.03.14 11:15
Оценка:
Здравствуйте, dipso, Вы писали:

D>Я Вас не понял. Тип — oncreated, конструктор — initialized.

На ходу название придумывал, потому что.

D>OnCreate — понятно, виртуальный. Но ведь сам T, и его предки в своём конструкторе тоже должны вызвать OnCreate, но они пока не знают о том что им его вызывать не надо. В общем не понял я, вашу мысль. А так да, вызов в каждом конструкторе OnCreate — самое простое решение. Нужно суметь решить — вызывать его или нет. Подъясните пожалуйста.


Мысль в том, что oncreated — это запаивающий класс вне иерархии основных классов.
class A { virtual void init(); };
class B: public A { virtual void init(); };
class C: public B { virtual void init(); };

template<class T> class Initialized : public T
{
  Initialized() { init(); }
};

Initialized<A> a;
Initialized<B> b;
Initialized<C> c;


Похожим образом устроены и коклассы в ATL, и оконные классы в WTL.
Перекуём баги на фичи!
Re[7]: Виртуальный конструктор
От: dipso  
Дата: 31.03.14 17:14
Оценка: :))
Здравствуйте, Кодт, Вы писали:
...
Может мы говорим о разных вещах.
Я пытаюсь:

В классическом С++ сделать то чего там нет в принципе.
Типа.

struct A
{
A(){}
virtual OnCreate(){}
};

struct B : public A
{
B(){}
OnCreate(){}
};

и надо штобы OnCreate вызывалось автоматически.

И прошу Вас, не сыпьте шаблонами. В данном случае — бойлерплейт.
Re[8]: Виртуальный конструктор
От: Кодт Россия  
Дата: 31.03.14 18:18
Оценка:
Здравствуйте, dipso, Вы писали:

D>Я пытаюсь:

D>В классическом С++ сделать то чего там нет в принципе.
D>И прошу Вас, не сыпьте шаблонами. В данном случае — бойлерплейт.

Хочешь кушать кактус — ради бога. Но плюсы от этого шарпом не станут.

В плюсах есть готовое, проверенное, легальное решение — разнести иерархию классов и их обёртки.
1) пимплы на умных указателях
2) запаивающие шаблоны
Последние имеют нулевой оверхед, и именно поэтому используются в промышленных библиотеках — ATL и WTL.
Причём WTL как раз оконная.

Обязательно надо изобрести свою WTL без блекджека и шлюх?
Перекуём баги на фичи!
Re[9]: Виртуальный конструктор
От: antonio_banderas Россия  
Дата: 01.04.14 16:30
Оценка:
Здравствуйте, Кодт, Вы писали:

К>В плюсах есть готовое, проверенное, легальное решение — разнести иерархию классов и их обёртки.

К>1) пимплы на умных указателях
К>2) запаивающие шаблоны
К>Последние имеют нулевой оверхед, и именно поэтому используются в промышленных библиотеках — ATL и WTL.
К>Причём WTL как раз оконная.

Про выделенное гугл ничего не знает. Вообще ничего.
Может, оно еще как-то по-другому называется?
Re[9]: Виртуальный конструктор
От: dipso  
Дата: 01.04.14 17:01
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, dipso, Вы писали:


D>>Я пытаюсь:

D>>В классическом С++ сделать то чего там нет в принципе.
D>>И прошу Вас, не сыпьте шаблонами. В данном случае — бойлерплейт.

К>Хочешь кушать кактус — ради бога. Но плюсы от этого шарпом не станут.


К>В плюсах есть готовое, проверенное, легальное решение — разнести иерархию классов и их обёртки.

К>1) пимплы на умных указателях
К>2) запаивающие шаблоны
К>Последние имеют нулевой оверхед, и именно поэтому используются в промышленных библиотеках — ATL и WTL.
К>Причём WTL как раз оконная.

К>Обязательно надо изобрести свою WTL без блекджека и шлюх?

Шлюхи были вчера, и WTL я любил, но боже, как давно это было. С некоторых пор люблю кроссплатформенность. Но может, как Вы советуете, перейти на новый стандрт, достали старые приколы и борьба с ними
Re[4]: Виртуальный конструктор
От: __kot2  
Дата: 01.04.14 19:12
Оценка:
Здравствуйте, dipso, Вы писали:
D>После вызова конструктора, до вызова инициализирующего метода, объект находится в подвешеном состоянии. Кто, когда и где его вызовет?
D>Вероятно ещё придётся ввести поле bool created и соответствующий метод, нужно решать что делать если created=false.
конструктор создан для конструирования обьекта. метод init не нужен

D>Тут говорили: много лишнего кода. В определении конструктора VCons vc=VCons(), передача vc в список инициализации, и наследование от Base(см.дальше).

а windows.h там зачем, например?
Re[5]: Виртуальный конструктор
От: dipso  
Дата: 02.04.14 00:42
Оценка:
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, dipso, Вы писали:

D>>После вызова конструктора, до вызова инициализирующего метода, объект находится в подвешеном состоянии. Кто, когда и где его вызовет?
D>>Вероятно ещё придётся ввести поле bool created и соответствующий метод, нужно решать что делать если created=false.
__>конструктор создан для конструирования обьекта. метод init не нужен

D>>Тут говорили: много лишнего кода. В определении конструктора VCons vc=VCons(), передача vc в список инициализации, и наследование от Base(см.дальше).

__>а windows.h там зачем, например?

Говорим о двухфазной инициализации. Неужели в C++ есть тот самый виртуальный конструктор?
windows.h отмакросен.Что не так?
Re[10]: Виртуальный конструктор
От: Jack128  
Дата: 02.04.14 09:08
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>Здравствуйте, Кодт, Вы писали:


К>>В плюсах есть готовое, проверенное, легальное решение — разнести иерархию классов и их обёртки.

К>>1) пимплы на умных указателях
К>>2) запаивающие шаблоны
К>>Последние имеют нулевой оверхед, и именно поэтому используются в промышленных библиотеках — ATL и WTL.
К>>Причём WTL как раз оконная.

_>Про выделенное гугл ничего не знает. Вообще ничего.

Гы, ну да, зато по запросу пимплы выдает мнго чего интересного LOL
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.