Re[4]: Так, кстати, логичнее, но непонятнее... ;)
От: Erop Россия  
Дата: 18.03.10 19:13
Оценка:
Здравствуйте, niralex, Вы писали:

N>Красиво... Это то, что надо.

Рад, что помог, но если ты расскажешь зачем это тебе, то может тут кто-нибудь что-нибудь менее хаккерское предложит...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Блин, спать пора
От: Erop Россия  
Дата: 18.03.10 19:49
Оценка:
Блин! "static" потерял ;(

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> static T* CreateNewObject() { return new RealObject<T>(); }
};
пример использования:
struct CTest : CrazyFactory::Root {
//    Раскомментируешь -- сломается!
//   CrazyFactory::CSeed CheckSeed( CrazyFactory::CSeed s ) { return s; }
};

void foo()
{
//    CTest t1;    //    Раскомментируешь -- сломается!
    delete CrazyFactory::CreateNewObject<CTest>();
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Блин, спать пора
От: niralex  
Дата: 18.03.10 21:43
Оценка:
Здравствуйте, Erop, Вы писали:

E>Блин! "static" потерял ;(


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> static T* CreateNewObject() { return new RealObject<T>(); }
E>};
E>
пример использования:
struct CTest : CrazyFactory::Root {
E>//    Раскомментируешь -- сломается!
E>//   CrazyFactory::CSeed CheckSeed( CrazyFactory::CSeed s ) { return s; }
E>};

E>void foo()
E>{
E>//    CTest t1;    //    Раскомментируешь -- сломается!
E>    delete CrazyFactory::CreateNewObject<CTest>();
E>}


это я уже все оформил...
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 // потомок
{ };

Но, это не главное. Вот идея, вот это да! Как такое в голову приходит? Я несколько дней мучался.
На счет того, зачем это нужно..., в двух словах — необходимо реализовать паттерн "Композит". Причем, чтобы для тех кто пишет код потомков было все как как можно более прозрачно и минимум возможностей допускать ошибки. А сама реализация подразумевает, что при объявлении объекта в классе(точнее интеллектуального указателя нанего), он автоматически добавляется в него как дочерний объект. И все объекты имеют обощенный интерфейс доступа к таким дочерним объектам. Это позволяет трактовать все объекты системы как рекурсивные композиты, имеющие унифицированный интерфейс доступа к вложенным объектам. Причем в классы-потомки об этом даже не "догадываются".
Re[5]: Блин, спать пора
От: Erop Россия  
Дата: 18.03.10 22:30
Оценка:
Здравствуйте, niralex, Вы писали:

N>Но, это не главное. Вот идея, вот это да! Как такое в голову приходит? Я несколько дней мучался.

Ну, как бы, мы ищем способ запретить создавать объект вне фабрики. В С++ не так много способов запретить создавать объекты. Абстрактный класс -- один из них.
Дальше дело техники...

N>Причем в классы-потомки об этом даже не "догадываются".


Ну мне так кажется, что просто комментария на тему о том, что наследники твоего интерфейса обязаны быть созданы по new было бы достаточно.
Вряд ли такого рода ошибки являются серьёзной проблемой.
С другой стороны, если делать с предложенным мной трюком, то пользователь попадёт в странную ситуацию.
Попробует создать объект своего класса и узнает, что
1) Он абстрактный
2) Есть функция, которую он не может определить, и при этом что она делает тоже не понятно
3) Фабрика, тем не менее, объекты его класса как-то создаёт...

Я предпочитаю поддерживать программы, где такого рода ребусов поменьше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: sidorov18 США  
Дата: 19.03.10 08:19
Оценка:
Здравствуйте, Erop, Вы писали:

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


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


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

E>public:
E>    NoStackObject() { checkThis(); }
E>    NoStackObject( const NoStackObject& ) { checkThis(); }
E>};
E>


Я так понял, что идея в том, что если объект класса создан на стеке, то разница адресов будет небольшая.
но в таком тесте:

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    NoStackObject nsto;//diff = -500
    NoStackObject* nsto_heap = new NoStackObject;//diff = -1804585
}

идей вроде верная, только почему в случае стековой переменной такая разница адресов?
Re: Как запретить создание объектов в памяти стека.
От: slava_phirsov Россия  
Дата: 19.03.10 09:19
Оценка: :))
Здравствуйте, Аноним, Вы писали:

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



S.Meyers: Effective C++, More effective C++ вам в помощь. Там есть одна глава, которая в точности соответствует теме. Хотя тут уже все подробно описали: private конструктор или деструктор + псевдоконструктор или псевдодеструктор. Остальное — изврат
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[5]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: rus blood Россия  
Дата: 19.03.10 09:27
Оценка: 2 (1)
Здравствуйте, sidorov18, Вы писали:

S>Я так понял, что идея в том, что если объект класса создан на стеке, то разница адресов будет небольшая.

S>но в таком тесте:
S>идей вроде верная, только почему в случае стековой переменной такая разница адресов?

Потому что место объекта на стеке резервируется заранее, в прологе функции.
А создание объекта (и проверка адреса локальной переменной) выполняется по ходу выполнения кода, когда адрес стека уже "уехал".
И уехать он может далеко...

Здесь, по хорошему, нужен адрес вершины стека потока, и доступ к текущему адресу стека (или адрес локальной переменной).
Под виндой вершину стека можно взять так
#include "winnt.h"
.............
void* stackBase = ((NT_TIB*)::NtCurrentTeb())->StackBase;
Имею скафандр — готов путешествовать!
Re[5]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Erop Россия  
Дата: 19.03.10 11:05
Оценка:
Здравствуйте, sidorov18, Вы писали:

S>Я так понял, что идея в том, что если объект класса создан на стеке, то разница адресов будет небольшая.

S>но в таком тесте:

S>
S>int APIENTRY _tWinMain(HINSTANCE hInstance,
S>                     HINSTANCE hPrevInstance,
S>                     LPTSTR    lpCmdLine,
S>                     int       nCmdShow)
S>{
S>    NoStackObject nsto;//diff = -500
S>    NoStackObject* nsto_heap = new NoStackObject;//diff = -1804585
S>}
S>

S>идей вроде верная, только почему в случае стековой переменной такая разница адресов?

Ну надо посмотреть что там такого в _tWinMain на стеке заводят неявно...

Но идея такая. Можно число "16" увеличить несколько. Но это всё всё равно не надёжно, на самом деле. Хотя от платформы зависит, конечно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Слышал звон... ;)
От: Erop Россия  
Дата: 19.03.10 11:06
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>S.Meyers: Effective C++, More effective C++ вам в помощь. Там есть одна глава, которая в точности соответствует теме. Хотя тут уже все подробно описали: private конструктор или деструктор + псевдоконструктор или псевдодеструктор. Остальное — изврат


Попа в том, что НЭ ПОМОЖЭТ...
ПАТАМУШТА ПРО ДРУГОЕ...

Упражнение для самостоятельного обдумывания: создать по new экземпляр наследника класса с приватным конструктором.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Erop Россия  
Дата: 19.03.10 11:08
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Под виндой вершину стека можно взять так

RB>
RB>#include "winnt.h"
RB>.............
RB>void* stackBase = ((NT_TIB*)::NtCurrentTeb())->StackBase;
RB>


Зачем такие сложности? Вполне можно просто взять адрес автоматической переменной в маленькой функции
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: rus blood Россия  
Дата: 19.03.10 11:40
Оценка:
Здравствуйте, Erop, Вы писали:

E>Зачем такие сложности? Вполне можно просто взять адрес автоматической переменной в маленькой функции


Я говорю про базу стека потока, а не про его вершину.
Про вершину было

доступ к текущему адресу стека (или адрес локальной переменной).

В скобках — твой вариант.
Имею скафандр — готов путешествовать!
Re[8]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Erop Россия  
Дата: 19.03.10 11:59
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Я говорю про базу стека потока, а не про его вершину.

Базы может и не быть. Стэк может быть списком фреймов, например...
Решение непереносимое в общем, и вообще рискованное.
IMHO, нефиг так делать. Я предлагал "подзажечь" исклбчительно в ответ на шутку коллеги

Я бы даже и решение с CrazyFactory не использовал бы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Как запретить создание объектов в памяти стека.
От: K13 http://akvis.com
Дата: 19.03.10 12:00
Оценка:
_>>>Перенести деструктор в защищенную секцию
K13>>Унаследоваться от такого класса — и вперед.

U>как сделать. чтобы не компилировалось?


я как раз и имел в виду, что защищенный деструктор не дает создавать на стеке экхемпляры именно этого класса, но легко позволяет делать это с наследниками. т.е. "Перенести деструктор в защищенную секцию" — не решение для ветки иерархии (включая наследников)
Re[9]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: rus blood Россия  
Дата: 19.03.10 12:19
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Базы может и не быть. Стэк может быть списком фреймов, например...


Есть пример фреймовой организации стека потока?
Имею скафандр — готов путешествовать!
Re[10]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Кодт Россия  
Дата: 19.03.10 12:57
Оценка: +1
Здравствуйте, rus blood, Вы писали:

RB>Есть пример фреймовой организации стека потока?


Smalltalk- и Lisp-машины?
Перекуём баги на фичи!
Re[10]: O!!! Ну тогда надо ЖЕЧЬ!!!! ;)
От: Erop Россия  
Дата: 19.03.10 13:10
Оценка: 3 (1)
Здравствуйте, rus blood, Вы писали:

RB>Есть пример фреймовой организации стека потока?

Конечно. На архитектурах, где легко адресовать память в маленьком сегменте, а вот сегментов может быть много...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Слышал звон... ;)
От: slava_phirsov Россия  
Дата: 23.03.10 11:49
Оценка: :)
Здравствуйте, Erop, Вы писали:

....

Домашнее задание: почитать Best practices (не обязательно упомянутое, можно и что-л. другое — по вкусу) и поискать в них чертежи разрабатываемого "Двухколесного движительного средства на мускульной тяге". Опыт показывает, что у чужого велосипеда коэффициент квадратности колес обычно значительно меньше, чем у самодельного.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[4]: Как хорошо уметь читать!!! ;)
От: Erop Россия  
Дата: 23.03.10 12:12
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Домашнее задание: почитать Best practices (не обязательно упомянутое, можно и что-л. другое — по вкусу) и поискать в них чертежи разрабатываемого "Двухколесного движительного средства на мускульной тяге". Опыт показывает, что у чужого велосипеда коэффициент квадратности колес обычно значительно меньше, чем у самодельного.


Не знаем, мы, не то что вы, пособиев по велосипедостроениям не читали
Вопрос был в том, как запретить создавать вне фабрики экземпляров НАСЛЕДНИКОВ некоего класса, а у Маерса про запрет создания экземпляров САМОГО класса.
Если ты сделаешь в базовом классе

private конструктор или деструктор + псевдоконструктор или псевдодеструктор

, то наследники станут вообще невозможны. А если они таки будут возможны, то ты всё равно не контролируешь доступность ИХ конструкторов...

Короче читай внимательнее, если такой умный, да?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Как хорошо уметь читать!!! ;)
От: slava_phirsov Россия  
Дата: 23.03.10 13:59
Оценка:
Здравствуйте, Erop, Вы писали:

E>Не знаем, мы, не то что вы, пособиев по велосипедостроениям не читали


Велосипедостроение оно на то и велосипедостроение, чтобы все самому, без пособиев.

E>Вопрос был в том, как запретить создавать вне фабрики экземпляров НАСЛЕДНИКОВ некоего класса, а у Маерса про запрет создания экземпляров САМОГО класса.


А также про то, почему вот такие фокусы
Автор: Erop
Дата: 18.03.10
не катят.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[6]: Как хорошо уметь читать!!! ;)
От: Erop Россия  
Дата: 23.03.10 14:16
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>А также про то, почему вот такие фокусы
Автор: Erop
Дата: 18.03.10
не катят.

Если ты не понял, напишу ещё раз : ЭТО БЫЛА ШУТКА!!!

А фокус не катит потому, что ненадёжный (можно нечаянно отмотать очень длинный стековый фрейм, например в результате inline-подстановок, и привет) и непереносимый к тому же...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.