Как запретить создание объектов в памяти стека.
От: Аноним  
Дата: 18.03.10 12:50
Оценка:
Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.
Re: Как запретить создание объектов в памяти стека.
От: placement_new  
Дата: 18.03.10 13:05
Оценка: +1 -1 :)
Здравствуйте, Аноним, Вы писали:

А>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.


Перенести деструктор в защищенную секцию
Re[2]: Как запретить создание объектов в памяти стека.
От: Кодт Россия  
Дата: 18.03.10 13:56
Оценка: +1 :))) :))) :))) :)))
Здравствуйте, placement_new, Вы писали:

_>Перенести деструктор в защищенную секцию


Твой никнейм как бы намекает...
Перекуём баги на фичи!
Re[2]: Как запретить создание объектов в памяти стека.
От: K13 http://akvis.com
Дата: 18.03.10 14:17
Оценка:
_>Перенести деструктор в защищенную секцию

Унаследоваться от такого класса — и вперед.
Re[3]: Как запретить создание объектов в памяти стека.
От: uzhas Ниоткуда  
Дата: 18.03.10 14:27
Оценка:
Здравствуйте, K13, Вы писали:

_>>Перенести деструктор в защищенную секцию


K13>Унаследоваться от такого класса — и вперед.


Поясните, что вы имеете в виду
Вот как я понял вашу рекомендацию:

class A
{
protected:
  virtual ~A() {}
};

class B : public A
{
};

int main()
{
  B b;
  return 0;
}


но этот код у меня компилируется =\
как сделать. чтобы не компилировалось?
Re[2]: Как запретить создание объектов в памяти стека.
От: niralex  
Дата: 18.03.10 14:29
Оценка:
Здравствуйте, placement_new, Вы писали:

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


А>>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.


_>Перенести деструктор в защищенную секцию


в protected? Тогда в производных классах также нужно сделать деструктор protected, но согласно начальному условию, изменять производные классы нельзя. А если в потомках оставить деструктор public, то объекты можно создавать в стековой памяти.
Re[2]: Как запретить создание объектов в памяти стека.
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 18.03.10 14:47
Оценка:
Здравствуйте, placement_new, Вы писали:

_>Перенести деструктор в защищенную секцию


лучше в private


class A
{
public:
    static A * Create()
    {
        return new A();
    }
private:
    A()
    {
    };
};
Re[3]: Как запретить создание объектов в памяти стека.
От: niralex  
Дата: 18.03.10 14:50
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

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


_>>Перенести деструктор в защищенную секцию


_>лучше в private



_>
_>class A
_>{
_>public:
_>    static A * Create()
_>    {
_>        return new A();
_>    }
_>private:
_>    A()
_>    {
_>    };
_>};
_>


тогда нельзя создать объект производного от А класса никаким спосом
Re: Как запретить создание объектов в памяти стека.
От: uzhas Ниоткуда  
Дата: 18.03.10 14:58
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>При этом производные классы изменять недопустимо, можно только базовый.


Спрячь наследников и предоставь фабрики, которые будут возвращать std::auto_ptr<Base>.
Тогда все клиенты отвалятся и будут вынуждены использовать фабрики =)
Re[4]: Как запретить создание объектов в памяти стека.
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 18.03.10 15:23
Оценка: -1
Здравствуйте, niralex, Вы писали:

N>тогда нельзя создать объект производного от А класса никаким спосом


можно так:


class A
{
public:
    static A * Create()
    {
        return new A();
    }
private:
    A()
    {
    };
};

class B : public A
{
public:
    B() : A(*A::Create())
    {
    };
};
Re[5]: Как запретить создание объектов в памяти стека.
От: Мишень-сан  
Дата: 18.03.10 15:31
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

_>можно так:


_>
_>class A
_>{
_>public:
_>    static A * Create()
_>    {
_>        return new A();
_>    }
_>private:
_>    A()
_>    {
_>    };
_>};

_>class B : public A
_>{
_>public:
_>      // а здесь имеем утечку - конструктор копии отработает,
_>      // но вот его аргумент, живущий в куче, потеряется.
_>    B() : A(*A::Create())
_>    {
_>    };
_>};
_>
Re[6]: Как запретить создание объектов в памяти стека.
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 18.03.10 15:39
Оценка: :)
_>>можно так:
_>> // а здесь имеем утечку — конструктор копии отработает,
_>> // но вот его аргумент, живущий в куче, потеряется.
_>> B() : A(*A::Create())
_>> {
_>> };
_>>};
_>>[/ccode]

это все зависит от того, как конструктор копирования будет выглядеть

на самом деле задача не тривиальная, как следствие решение (если таковое есть) будет тоже извращенным
Re[7]: Как запретить создание объектов в памяти стека.
От: Мишень-сан  
Дата: 18.03.10 15:52
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

_>это все зависит от того, как конструктор копирования будет выглядеть

_>на самом деле задача не тривиальная, как следствие решение (если таковое есть) будет тоже извращенным

Насколько я знаю, нормального решения именно для иерархии при такой постановке нет.
Пока единственное хоть сколько-нибудь рабочее — заныкать иерархию и отдавать через фабрики. Тоже метод в общем-то.

А по поводу конструктора копии —
A(const A& other)
{
    // ... здесь конструируем
    // ... а потом - серпом по яйцам!
    A* ptr = const_cast<A*>(&other);
    delete A;
}

Это имеете ввиду?

Думаю, не нужно говорить, что случится, если кто-то, создавая иерархию, передаст туда временный объект...
Re[8]: Как запретить создание объектов в памяти стека.
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 18.03.10 16:00
Оценка:
Здравствуйте, Мишень-сан, Вы писали:

МС>А по поводу конструктора копии —

МС>
МС>A(const A& other)
МС>{
МС>    // ... здесь конструируем
МС>    // ... а потом - серпом по яйцам!
МС>    A* ptr = const_cast<A*>(&other);
МС>    delete A;
МС>}
МС>

МС>Это имеете ввиду?

МС>Думаю, не нужно говорить, что случится, если кто-то, создавая иерархию, передаст туда временный объект...


я не говрил о конкретной реализации, но придумать что-то можно, например в вашем случае если передавать в конструктор копирования не константную ссылку, то временный объект туда никто не передаст, но опять таки нужно думать чтоб придумать что-то стоящее я просто предложил направление для размышления
Re[8]: Как запретить создание объектов в памяти стека.
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 18.03.10 16:15
Оценка:
Здравствуйте, Мишень-сан, Вы писали:

например так можно так попробовать:

class A
{
public:
    static A * Create()
    {
        return new A();
    }
protected:
    A(A &a)
    {
        //копируем
        //........
        //........
        //удаляем
        A * a_ =  &a;
        delete a_;
    };

    A(const A & a)
    {
        //копируем 
        //........
        //........
        //и не удаляем
    };
private:
    A()
    {
    };
};

class B : public A
{
public:
    B() : A(*A::Create())
    {
    };
};
Re: А зачем всё это надо?
От: Erop Россия  
Дата: 18.03.10 16:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.


А зачем всё это надо?

Можно, например, завести какой-нибудь объект, к которому у наследников нет доступа, и чисто-виртуальный метод, в реализации которого нужен доступ к этому объекту, ну и вперёд. Создавать объекты производных классов сможет только твоя фабрика
class CrazyFactory {
    struct CSeed { };
    template<typename T> class RealObject : public T {
        CSeed CheckSeed( CSeed s ) { return s; }
    };
public:
    class Root {
    public:
        virtual ~Root() {};
    private:
        virtual CSeed CheckSeed( CSeed ) = 0;
    };

    template<typename T> Root* CreateNewObject() { return new RealObject<T>(); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Так, кстати, логичнее, но непонятнее... ;)
От: Erop Россия  
Дата: 18.03.10 16:31
Оценка: 6 (2)
class CrazyFactory {
    struct CSeed { };
    template<typename T> class RealObject : public T {
        CSeed CheckSeed( CSeed s ) { return s; }
    };
public:
    class Root {
    public:
        virtual ~Root() {};
    private:
        virtual CSeed CheckSeed( CSeed ) = 0;
    };

    template<typename T> T* CreateNewObject() { return new RealObject<T>(); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: А зачем всё это надо?
От: Feonyf  
Дата: 18.03.10 16:33
Оценка: 3 (1) +1 :))) :))) :))
Здравствуйте, Erop, Вы писали:

E>А зачем всё это надо?


Наверно у них какой-то объект стек портит и они защищаются таким образом от порчи стека.
Моя строка построения буста:
.\bjam link=static threading=multi runtime-link=static -j %NUMBER_OF_PROCESSORS% --with-filesystem --with-thread --with-date_time address-model=64
Re[3]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Erop Россия  
Дата: 18.03.10 16:49
Оценка: :)
Здравствуйте, Feonyf, Вы писали:

F>Наверно у них какой-то объект стек портит и они защищаются таким образом от порчи стека.


О! Тогда можно подзажечь по-взрослому:
class NoStackObject {
    enum { MaxDiff = sizeof( void* ) * 16 };
    void checkThis() const
    {
        char a;
        int diff = &a - (const char*)this;
        assert( -MaxDiff <= diff && diff <= MaxDiff );
    }

public:
    NoStackObject() { checkThis(); }
    NoStackObject( const NoStackObject& ) { checkThis(); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Так, кстати, логичнее, но непонятнее... ;)
От: niralex  
Дата: 18.03.10 18:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>
class CrazyFactory {
E>    struct CSeed { };
E>    template<typename T> class RealObject : public T {
E>        CSeed CheckSeed( CSeed s ) { return s; }
E>    };
E>public:
E>    class Root {
E>    public:
E>        virtual ~Root() {};
E>    private:
E>        virtual CSeed CheckSeed( CSeed ) = 0;
E>    };

E>    template<typename T> T* CreateNewObject() { return new RealObject<T>(); }
E>};
E>


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