Здравствуйте, Аноним, Вы писали:
А>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: 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> T* CreateNewObject() { return new RealObject<T>(); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как запретить создание объектов в памяти стека.
Здравствуйте, Аноним, Вы писали:
А>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.
S.Meyers: Effective C++, More effective C++ вам в помощь. Там есть одна глава, которая в точности соответствует теме. Хотя тут уже все подробно описали: private конструктор или деструктор + псевдоконструктор или псевдодеструктор. Остальное — изврат
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, rus blood, Вы писали:
RB>Есть пример фреймовой организации стека потока?
Конечно. На архитектурах, где легко адресовать память в маленьком сегменте, а вот сегментов может быть много...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, sidorov18, Вы писали:
S>Я так понял, что идея в том, что если объект класса создан на стеке, то разница адресов будет небольшая. S>но в таком тесте: S>идей вроде верная, только почему в случае стековой переменной такая разница адресов?
Потому что место объекта на стеке резервируется заранее, в прологе функции.
А создание объекта (и проверка адреса локальной переменной) выполняется по ходу выполнения кода, когда адрес стека уже "уехал".
И уехать он может далеко...
Здесь, по хорошему, нужен адрес вершины стека потока, и доступ к текущему адресу стека (или адрес локальной переменной).
Под виндой вершину стека можно взять так
Здравствуйте, Аноним, Вы писали:
А>При этом производные классы изменять недопустимо, можно только базовый.
Спрячь наследников и предоставь фабрики, которые будут возвращать std::auto_ptr<Base>.
Тогда все клиенты отвалятся и будут вынуждены использовать фабрики =)
Re[4]: Как запретить создание объектов в памяти стека.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Домашнее задание: почитать Best practices (не обязательно упомянутое, можно и что-л. другое — по вкусу) и поискать в них чертежи разрабатываемого "Двухколесного движительного средства на мускульной тяге". Опыт показывает, что у чужого велосипеда коэффициент квадратности колес обычно значительно меньше, чем у самодельного.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, Erop, Вы писали:
E> Если ты не понял, напишу ещё раз : ЭТО БЫЛА ШУТКА!!!
А, ну извини, погорячился.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Как запретить создание объектов в памяти стека.
От:
Аноним
Дата:
18.03.10 12:50
Оценка:
Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.
Re[2]: Как запретить создание объектов в памяти стека.
Здравствуйте, placement_new, Вы писали:
_>Здравствуйте, Аноним, Вы писали:
А>>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: Type ob; // должно приводить к ошибке компиляции), а разрешить только в динамической(с помощью new)? При этом производные классы изменять недопустимо, можно только базовый.
_>Перенести деструктор в защищенную секцию
в protected? Тогда в производных классах также нужно сделать деструктор protected, но согласно начальному условию, изменять производные классы нельзя. А если в потомках оставить деструктор public, то объекты можно создавать в стековой памяти.
Re[2]: Как запретить создание объектов в памяти стека.
Здравствуйте, dabeat_bf, Вы писали:
_>это все зависит от того, как конструктор копирования будет выглядеть _>на самом деле задача не тривиальная, как следствие решение (если таковое есть) будет тоже извращенным
Насколько я знаю, нормального решения именно для иерархии при такой постановке нет.
Пока единственное хоть сколько-нибудь рабочее — заныкать иерархию и отдавать через фабрики. Тоже метод в общем-то.
А по поводу конструктора копии —
A(const A& other)
{
// ... здесь конструируем
// ... а потом - серпом по яйцам!
A* ptr = const_cast<A*>(&other);
delete A;
}
Это имеете ввиду?
Думаю, не нужно говорить, что случится, если кто-то, создавая иерархию, передаст туда временный объект...
Re[8]: Как запретить создание объектов в памяти стека.
Здравствуйте, Мишень-сан, Вы писали:
МС>А по поводу конструктора копии — МС>
МС>A(const A& other)
МС>{
МС> // ... здесь конструируем
МС> // ... а потом - серпом по яйцам!
МС> A* ptr = const_cast<A*>(&other);
МС> delete A;
МС>}
МС>
МС>Это имеете ввиду?
МС>Думаю, не нужно говорить, что случится, если кто-то, создавая иерархию, передаст туда временный объект...
я не говрил о конкретной реализации, но придумать что-то можно, например в вашем случае если передавать в конструктор копирования не константную ссылку, то временный объект туда никто не передаст, но опять таки нужно думать чтоб придумать что-то стоящее я просто предложил направление для размышления
Re[8]: Как запретить создание объектов в памяти стека.
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())
{
};
};
Здравствуйте, Аноним, Вы писали:
А>Есть полиморфная иерархия классов. Необходимо запретить создание объектов классов этой иерархии в памяти стека(например: 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>(); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, niralex, Вы писали:
N>Красиво... Это то, что надо.
Рад, что помог, но если ты расскажешь зачем это тебе, то может тут кто-нибудь что-нибудь менее хаккерское предложит...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
это я уже все оформил...
class A
{
private:
class T{};
virtual T f()=0;
template<class Type>
class Temp : public Type
{
T f() {}
};
public:
virtual ~A(){}
template<class Type>
static Type *Create()
{
return new Temp<Type>();
}
};
class B : public A // потомок
{ };
Но, это не главное. Вот идея, вот это да! Как такое в голову приходит? Я несколько дней мучался.
На счет того, зачем это нужно..., в двух словах — необходимо реализовать паттерн "Композит". Причем, чтобы для тех кто пишет код потомков было все как как можно более прозрачно и минимум возможностей допускать ошибки. А сама реализация подразумевает, что при объявлении объекта в классе(точнее интеллектуального указателя нанего), он автоматически добавляется в него как дочерний объект. И все объекты имеют обощенный интерфейс доступа к таким дочерним объектам. Это позволяет трактовать все объекты системы как рекурсивные композиты, имеющие унифицированный интерфейс доступа к вложенным объектам. Причем в классы-потомки об этом даже не "догадываются".
Здравствуйте, niralex, Вы писали:
N>Но, это не главное. Вот идея, вот это да! Как такое в голову приходит? Я несколько дней мучался.
Ну, как бы, мы ищем способ запретить создавать объект вне фабрики. В С++ не так много способов запретить создавать объекты. Абстрактный класс -- один из них.
Дальше дело техники...
N>Причем в классы-потомки об этом даже не "догадываются".
Ну мне так кажется, что просто комментария на тему о том, что наследники твоего интерфейса обязаны быть созданы по new было бы достаточно.
Вряд ли такого рода ошибки являются серьёзной проблемой.
С другой стороны, если делать с предложенным мной трюком, то пользователь попадёт в странную ситуацию.
Попробует создать объект своего класса и узнает, что
1) Он абстрактный
2) Есть функция, которую он не может определить, и при этом что она делает тоже не понятно
3) Фабрика, тем не менее, объекты его класса как-то создаёт...
Я предпочитаю поддерживать программы, где такого рода ребусов поменьше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Feonyf, Вы писали:
F>>Наверно у них какой-то объект стек портит и они защищаются таким образом от порчи стека.
E>О! Тогда можно подзажечь по-взрослому:
Здравствуйте, sidorov18, Вы писали:
S>Я так понял, что идея в том, что если объект класса создан на стеке, то разница адресов будет небольшая. S>но в таком тесте:
S>
S>идей вроде верная, только почему в случае стековой переменной такая разница адресов?
Ну надо посмотреть что там такого в _tWinMain на стеке заводят неявно...
Но идея такая. Можно число "16" увеличить несколько. Но это всё всё равно не надёжно, на самом деле. Хотя от платформы зависит, конечно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, slava_phirsov, Вы писали:
_>S.Meyers: Effective C++, More effective C++ вам в помощь. Там есть одна глава, которая в точности соответствует теме. Хотя тут уже все подробно описали: private конструктор или деструктор + псевдоконструктор или псевдодеструктор. Остальное — изврат
Попа в том, что НЭ ПОМОЖЭТ...
ПАТАМУШТА ПРО ДРУГОЕ...
Упражнение для самостоятельного обдумывания: создать по new экземпляр наследника класса с приватным конструктором.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Зачем такие сложности? Вполне можно просто взять адрес автоматической переменной в маленькой функции
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rus blood, Вы писали:
RB>Я говорю про базу стека потока, а не про его вершину.
Базы может и не быть. Стэк может быть списком фреймов, например...
Решение непереносимое в общем, и вообще рискованное.
IMHO, нефиг так делать. Я предлагал "подзажечь" исклбчительно в ответ на шутку коллеги
Я бы даже и решение с CrazyFactory не использовал бы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Как запретить создание объектов в памяти стека.
_>>>Перенести деструктор в защищенную секцию K13>>Унаследоваться от такого класса — и вперед.
U>как сделать. чтобы не компилировалось?
я как раз и имел в виду, что защищенный деструктор не дает создавать на стеке экхемпляры именно этого класса, но легко позволяет делать это с наследниками. т.е. "Перенести деструктор в защищенную секцию" — не решение для ветки иерархии (включая наследников)
Здравствуйте, slava_phirsov, Вы писали:
_>Домашнее задание: почитать Best practices (не обязательно упомянутое, можно и что-л. другое — по вкусу) и поискать в них чертежи разрабатываемого "Двухколесного движительного средства на мускульной тяге". Опыт показывает, что у чужого велосипеда коэффициент квадратности колес обычно значительно меньше, чем у самодельного.
Не знаем, мы, не то что вы, пособиев по велосипедостроениям не читали
Вопрос был в том, как запретить создавать вне фабрики экземпляров НАСЛЕДНИКОВ некоего класса, а у Маерса про запрет создания экземпляров САМОГО класса.
Если ты сделаешь в базовом классе
private конструктор или деструктор + псевдоконструктор или псевдодеструктор
, то наследники станут вообще невозможны. А если они таки будут возможны, то ты всё равно не контролируешь доступность ИХ конструкторов...
Короче читай внимательнее, если такой умный, да?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Не знаем, мы, не то что вы, пособиев по велосипедостроениям не читали
Велосипедостроение оно на то и велосипедостроение, чтобы все самому, без пособиев.
E>Вопрос был в том, как запретить создавать вне фабрики экземпляров НАСЛЕДНИКОВ некоего класса, а у Маерса про запрет создания экземпляров САМОГО класса.
не катят. Если ты не понял, напишу ещё раз : ЭТО БЫЛА ШУТКА!!!
А фокус не катит потому, что ненадёжный (можно нечаянно отмотать очень длинный стековый фрейм, например в результате inline-подстановок, и привет) и непереносимый к тому же...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском