На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Objective C в С++? , Возможна ли смена парадигмы-принципа без смены компилятора?
    1. Objective C как язык.

    2. Obj C to C++ откуда пришла идея?

    3. Общие теоретические принципы:
    Скрытый текст

    1. Тип можно представить как массив (или список) переменных и функций.

    2. Если этот принцип дополнить принципом objective C (он же слот/сигнал, он же «принцип win API», он же рецийвер-рефлектор Иррлихта, он же sf::Event SFML).
    То тип уже можно представить как «чёрный ящик» содержащий переменные, управление которыми осуществляется посредством функций.
    Это управление осуществляется с помощью единственной ф-ции «reflect» принимающий «события» или «сигналы» и содержащая «отражающую матрицу», то есть массив или список «функций реакции».


    3. То есть из 2 первых принципов следует:
    а) то, что существует необходимость лишь в массиве функций. Массив переменных уже избыточен;
    б) переменные можно представить не массивом, а структурой Си (для облегчения манипуляций с ними как с единым целым, применительно к Иррлихту: вместо Си структуры просто берётся указатель на ноду иди элемент – имеем оригинальный паттерн Proxy);
    в) тогда классу C++ останется лишь управление памятью (конструктор/деструктор) и единственная функция:
    ExpandedWrap disabled
      template <class T, class U>
      void reflect ( U & _selfData_, T & _SMessageEvent_ )
      {
      /// матрица отражающая событие
      }


    4. Следствия.
    а) В отличие от обычного порядка определений ф-ций класса такой подход теоретически позволят «добавлять классу функции налету» (то есть после его определения).

    б) Частично отпадает необходимость в вирт. Наследовании и кастах, теперь класс представляет собой «конструктор» состоящий из различных комбинаций элементов, в первую очередь отражающих функций и переменных. Сигнал (message, event, функтор) отделён от слота и может «приниматься» слотами объектов различных типов. Слот может добавляться типу после его определения. Наличие функций и переменных класса можно проверить. Можно идентифицировать класс или получить информацию о нём через наличие опред. ф-ций или их комбинации (для этого даже не нужно знать тип объекта!);

    5. Вышеописанное – это принципы. Дальше реализации «технологии».
    А реализована она может быть несколькими способами (возможно даже описаны не все):
    а) с помощью switch/case (подход из Иррлихта) или определения элемента в массива по ID;
    б) с помощью виртуального наследования или [массива + enum-ератов];
    в) с помощью частич. специализации шаблонов и списка функторов.

    Последний метод:
    а) в принципе, быстр, так как ветвление с «выбором класса по типу» переносится на этап компиляции;
    б) позволяет добавлять типу ф-ции в любой момент, уже после его объявления;
    в) чтобы функтор имел доступ к приватным переменным класса они просто передаются ему Си-структорой или указателем на ноду Иррлихта. В функции reflection класса. То есть ф-тор принимает 2 переменные структуру данных типа и «событие» или «message» – как Си структуру или же другой функтор.


    Чутка «флуда» по маршалингу/скриптам, GUI:
    Скрытый текст

    1. Так как в программировании не существует других данных кроме цифровых и текстовых, то при сведении данных к тексту выгоднее использовать скриптовый порт (что облегчит и сохранение/загрузку данных и их передачу текстовым GUI).

    2. И для маршалинга текстовых и для маршаллинга числовых данных удобнее всего использовать потоки C++ (std::stringstream). Текстовые для сведения к текстовым данным, они же предоставляют наиболее удобный инструментарий для парсинга-обработки текста. И числовые для сведения к цифровой форме. Структуры Си содержащие простые Си-данные можно загонять в числовой (например файловый) поток «целиком».

    3. Хотя для работы с «сериализованными» данными было бы удобно иметь специальную «потоковую БД», некий «ускоренный/оптимизированный» аналог std::map (по парам ключ-значение). Или что-то вроде этого. Суть – БД (осущ. быструю работу с упорядоченными, универсал. (сведённ. к единой форме хранения) данными).

    4. Данные GUI оч. удобно хранить в HTML + CSS (на худой конец XML). Парсинг данных к XML/HTML и обратно (суть сериализовать данные из контролов, записать в HTML БД, потом считать оттуда, записать обратно в контрол) удобнее всего осуществлять средствами скриптов поддерживающих регулярные выражения (или) (Lua, JavaScript: V8, Пайтон (Python) и т. д.)


    4. Релизация принципа Obj C посредством частичной специализации шаблонов C++:
    (компилировалось minGW 441, code::blocks, winXP SP1, необходима поддержка компилятором частичной специализации шаблонов)
    (но в теории должно компилироваться на любом компиляторе)

    Файл TObjectiveTFR.h (type functor-reflector MSG)
    Скрытый текст

    ExpandedWrap disabled
      #ifndef TOBJECTIVETFR_H_INCLUDED
      #define TOBJECTIVETFR_H_INCLUDED
       
      #include <iostream>
      #include <sstream>
       
      /// сначала создаёт eventmsg. Его задача "соединить"
      /// "внутренности класса" с внешним процессом, например ф-цией динамической библиотеки
      /// даже если она не содержит переменных структура должна существовать
      /// т.к. именно в ней хранится "возвращаемый результат"
       
      /// START namespace tfr
      namespace tfr /// type functor-reflector MSG
      {
      /// то, что необходимо всем структурам...
          struct tfr_mini
          {
          ///
              bool isExists;
              void exists ( bool _isExists_ ) { isExists = _isExists_; }
              bool exists () const { return isExists; }
       
              tfr_mini() { exists (true); }
       
              void check ( const char * _file_, std::size_t _line_)
              {
                  if ( ! isExists )
                  {
                      std::cout << "ERR: [tfr_list<T>]: Eventmsg not exist!" << "\n"
                                << "[FILE] = [" << _file_ << "]\n"
                                << "[LINE] = [" << _line_ << "]\n" << std::endl;
                  }
              }
          ///
          };
       
       
      /// результат сведения данных типа к тексту
          struct SDataAsText : public tfr_mini
          {
          ///
              std::string str;
          };
       
      /// получить данны TObjective типа
          struct SGetSet : public tfr_mini
          {
              TObjective::SData data_;
              bool isSet;
       
              SGetSet() { isSet = true; data_ = (TObjective::SData) { 0.f,0.f,0.f }; }
          ///
              void getset ( TObjective::SData & _data_ )
              {
                  if ( isSet )
                      _data_ = data_;
                  else /// get
                      data_ = _data_;
              }
          };
       
      /// результат операции сложения
          struct SAdd : public tfr_mini
          {
              float result;
          };
       
      ///
          struct SNull : public tfr_mini
          {};
      }
      /// END namespace tfr
       
      #endif // TOBJECTIVETFR_H_INCLUDED



    Файл TObjective.h
    Скрытый текст

    ExpandedWrap disabled
      #ifndef TOBJECTIVE_H_INCLUDED
      #define TOBJECTIVE_H_INCLUDED
       
      /// Эмуляция-симуляция Obj C типа в C++
          class TObjective
          {
          public:
              struct SData
              { float x,y,z; }; /// все переменные класса
          ///
          private:
              SData data_;
       
          public:
          ///
              template < class T > struct tfr_list /// type functor-reflectors list
              {
              /// default result (if this T not add in tfr_list )
                  static void exec ( SData & _data_,T & _eventmsg_ )
                  { _eventmsg_.exists( false ); }
              };
          ///
              TObjective() { data_ = (TObjective::SData) { 5.f,10.f,15.f }; }
              ~TObjective() { data_ = (TObjective::SData) { 0.f,0.f,0.f }; }
       
          ///
              template < class U >
              void rf ( U & _eventmsg_  ) // reflect
              {
                  tfr_list < U >::exec( data_,_eventmsg_ );
              }
          };
       
      #endif // TOBJECTIVE_H_INCLUDED



    Файл TObjective.cpp
    Скрытый текст

    ExpandedWrap disabled
      #include "TObjective.h"
      #include "TObjectiveTFR.h"
       
      ///
       
      /// START [SDataAsText]
          template<> struct TObjective::tfr_list < tfr::SDataAsText >
          {
              static void exec ( TObjective::SData & _data_,  tfr::SDataAsText & _eventmsg_ )
              {
                  std::stringstream s;
                  s << "[START TObjective]\n"
                    << "[x] \t= [" << _data_.x << "] \t= [float]\n"
                    << "[y] \t= [" << _data_.y << "] \t= [float]\n"
                    << "[z] \t= [" << _data_.z << "] \t= [float]\n"
       
                    << "[MSG] \t= [tfr::SDataAsText]\n"
                    << "[MSG] \t= [tfr::SGetSet]\n"
                    << "[MSG] \t= [tfr::SAdd]\n"
                    << "[END TObjective]\n";
       
                  _eventmsg_.str = s.str();
              }
          }; /// tfr_SDataAsText; // в экземпляре можно сконстр. список ф-ций типа
       
      /// END [SDataAsText]
       
       
      /// START [SGetSet]
          template<> struct TObjective::tfr_list <  tfr::SGetSet >
          {
              static void exec ( TObjective::SData & _data_, tfr::SGetSet & _eventmsg_ )
              {
                  _eventmsg_.getset( _data_ );
              }
          };
       
      /// END [SGetSet]
       
       
      /// START [SAdd]
          template<> struct TObjective::tfr_list < tfr::SAdd >
          {
              static void exec ( TObjective::SData & _data_, tfr::SAdd & _eventmsg_ )
              {
                  _eventmsg_.result = _data_.x + _data_.y + _data_.z;
              }
          };
       
      /// END [SAdd]



    Несколько тестов в main.cpp
    Скрытый текст

    ExpandedWrap disabled
      #include <iostream>
      #include "TObjective.cpp"
       
      using namespace std;
       
      /// при сздании новых файлов заголовок дублируется, менятся лишь имя файла И (!!! внимание !!!) структура-набор данных!)
       
      /// несколько тестов напоследок
      int main()
      {
      /// тестовый obj C тип
          TObjective obj;
       
      /// создать события
          tfr::SAdd add_msg;
          tfr::SGetSet getset_msg;
          tfr::SDataAsText asText_msg;
       
      /// последовательно "отправить" их типу, получить реакцию, отобразить
          obj.rf( asText_msg );
          cout << asText_msg.str << "\n";
       
          obj.rf( add_msg );
          add_msg.check( __FILE__, __LINE__ );
          cout << "result = " << add_msg.result << "\n\n"; // 30
       
          getset_msg.data_ = (TObjective::SData) { 30.f,35.f,35.f };
          obj.rf( getset_msg );
          getset_msg.check( __FILE__, __LINE__ );
          obj.rf( add_msg );
          obj.rf( asText_msg );
          asText_msg.check( __FILE__, __LINE__ );
          cout << asText_msg.str << endl;
       
          getset_msg.data_ = (TObjective::SData) { 100.f,100.f,100.f };
          getset_msg.isSet = false; // get
          obj.rf( getset_msg );
          cout << "x = " << getset_msg.data_.x << "\n"
               << "y = " << getset_msg.data_.y << "\n"
               << "z = " << getset_msg.data_.z << "\n\n";
       
          getset_msg.data_ = (TObjective::SData) { 100.f,100.f,100.f };
          getset_msg.isSet = true; // set
          obj.rf( getset_msg );
          obj.rf( add_msg );
          cout << "result = " << add_msg.result << "\n\n";
       
      /* /// ошибка компиляции: всё правильно (проверка на этапе комп.)
          struct SNULL
          {} snull;
          obj.rf( snull );
      */
      /// 2 вариант ошибки: посылка необрабатываемого сообщения
          tfr::SNull snull;
          obj.rf( snull );
          snull.check( __FILE__, __LINE__ );
       
          cout << "Press ENTER to exit!" << endl;
          cin.get();
          return 0;
      }



    5. Реализация принципа Obj C посредством класса как массива модулей периода исполнения:
    Скрытый текст

    Другой вариант это:
    1. Добавление в класс С++ Си-массива SAny * elem_arr имеющего вид:
    ExpandedWrap disabled
      struct SAny
      {
          unsigned t_id;
          char t_name [64];
          void * o_ptr;
       
      /// это или а) ф-ция или б) тип C++ c конструктором и его аргументами
          unsigned char f_args; /// вряд ли больше 256 арг...
          SAny * fa_arr;
      };


    2. Ф-ция reflection () не на шаблонах, а на ID.
    3. Т.е. класс - это массив переменных и функций, без различий между перем. и функ.
    4. Что позволит "автоматизировать" составление массива перем и функц. (отображ. внутр структ. Obj C класса)
    5. Остаётся лишь реализовать рассчёт ID один из возможных вариантов которого:
    5.1- На этапе комилляции:
    Как добавить ID типу/классу, если изначально ID у него нет?

    5.2 На этапе исполнения:
    ExpandedWrap disabled
          int t_id = 0;
          SAny type_t;
      ///
          class T
          {
              SAny & my_type;
          public:
              T()
              : my_type ( type_t )
              {}
          };
       
      /// а где-то здесь, уже после опред. класса T,
      /// например, в конструкторе фабрики (или
      /// конструкторе функтора-вирт конструктора),
      /// type_t инициализируется значениями,
      /// учитывая определение класса T
      /// type_t = (SAny) { t_id++,"T", ...



    ===================================

    Такая вот C++ поэзия. Надо быстрей записать, пока не настигла амнезия.
    Жаль об этом всём в книгах C++ ни слова. Ни слова c 1983?
    Меж тем трудосберегающий синтаксис Obj C во всю применяется в коммерческих разработках Apple, макинтош, Mac OS.
    Как так? Вот незадача.
      Возможна ли смена парадигмы-принципа без смены компилятора? Утверждать на 100% не буду, слишком много парадигм и языков. Но удачные примеры есть. Если парочку навскидку:

      1) Фреймворк Qt. Расширяет синтаксис "своего" С++ посредством предкомпиляции, используя MOC. Таким образом, к примеру, появляется возможность использования сигналов и слотов, прямо в описаниях и реализации классов.

      2) Язык Perl. Изначально - процедурно-ориентированный. Но возможности языка позволяют достаточно нехитрым способом конструировать классы и использовать парадигму ООП там, где ее изначально не было.
        Насчёт MOC было бы интересно. Что это и с чем его едят?
        Какие существуют способы расширения возможностей прекомпиляции?
        Или это свой язык-компилятор писать, что для Qt и осуществлено?
        И если так, то зачем? Если уже существует Obj C, где это реализовано?
        Не проще ли было воспользоваться возможностями Obj C?

        Действительно, гораздо понятнее, малотрудозатратно определять иниц. перем. как-то так:
        Скрытый текст
        ExpandedWrap disabled
          class T
          {
          public:
              struct Data
              {
                  int x;
                  float y;
                  double z;
                  char pch[64];
              }
           
          private:
              Data data_;
           
          public:
              T ( T::Data * _newd_ = 0 )
              {
              /// по умолчанию
                  data_ = (T::Data) { 15,87.f,150.f,"DefaultS" };
              /// если пользователь инициировал:
                  if ( _newd_ ) data_ = (*_newd_);
           
                  /// типы созданные с помощью new, malloc, realloc
                  /// (тот же std::string) невозможно передавать из dll в dll (разные
                  /// адресные пространства), значит в любом случае типы созданные
                  /// new, malloc, realloc было бы полезно помечать как "в динамич. памяти"
                  /// и в каком адресном протранстве (id dll) к тому же....
                  /// на уровне данных объекта? Конструктор-копировщик это вряд ли осилит
              }
          };

        Скрытый текст
        А в учебниках С++ чему учат? Тому, что нужно по 1 переменной "прищёлкивать"? И всё переписывать по 2-3 раза заново, определяя один и тот же класс?
        Копировать из тела класса копипастом, заменять точки с запятыми - одними запятыми, потом всё заново: брать каждую переменную в скобочки, двоеточие, потом запятые...
        А при описани нового типа - опять всё заново.
        Что-то оно как-то.... "есть как надо" что ли? И "есть методы для тех, от кого отделаться надо, а если невозможно, то пусть на неудобъях ломаются и ничего толком в итоге" чтоли?

        И вроде бы есть хороший язык... но никто не расскажет как нужно на нём что-то делать, чтобы не просто труд потратить, но и результат получить.
        И все говорят о "быстром развитии постоянн. меняющ. совр. технологий", при этом мечтают о типах по void*, а они реализованы в Obj C в 1983... как-то уже, то есть... и это имеет коммерческое применение десятилетиями... но новичкам говорят, что "это не правильно и не нужно"... и программисты Си "с коммерческой точки зрения" никому ненужны, хотя Mac OS, Cocoa, - вот же они.

        Какое-то такое впечатление. Непонятное.


        Конечный вопрос: Что легче?
        Легче взять компилятор Obj C и написать все необходимыепорты к OGL и вообще всему (свой "фреймворк к win/linux")?
        Или легче взять Obj C++, подцепить к существующим кодам? Пишут ещё, что расширение файлов Obj C *.m, а Obj C++ *.mm. Но нигде не написано, что нужно сделать чтобы перейти с одного на другое, просто файл переимновать или ещё что-то нужно?

        Или проще реализовать принципы Obj C в C++ и пользовать? Пока склоняюсь к последнему.
          Цитата SectorbzC @
          Действительно, гораздо понятнее, малотрудозатратно определять иниц. перем. как-то так:

          А если я захочу добавить в класс еще одну переменную?
            Цитата SectorbzC @
            Действительно, гораздо понятнее, малотрудозатратно определять иниц. перем. как-то так:
            ...
            А теперь перепутай инициализаторы местами в списке. Или пропусти один при подготовке своего _newd_. Или внеси туда агрегат. Вложенный в другой.
            Цитата SectorbzC @
            ExpandedWrap disabled
                      /// типы созданные с помощью new, malloc, realloc
                      /// (тот же std::string) невозможно передавать из dll в dll (разные
                      /// адресные пространства), ...

            С помощью malloc и realloc нельзя создать std::string, можно только зарезервировать место под него. Из dll в dll можно передавать всё, если не нарушается ODR. Если нарушается, то программа неверна сама по себе, без всяких dll или lib. Разные адресные пространства подразумевают наличие нескольких различных программ. Стандарт языка не описывает подобные конгломераты, это должно выполняться посредством API используемых ОСей или в конце концов third-party библиотеками.
              Цитата Qraizer @
              С помощью malloc и realloc нельзя создать std::string, можно только зарезервировать место под него.


              Заранее бъю челом ... вельми понеже, паки-паки, иже херувимы (С) :P Разве нельзя создать нужную структуру в памяти и произвести приведение типов? Присвоить переменной адрес вручную созданной структуры?

              Цитата SectorbzC @
              Насчёт MOC было бы интересно. Что это и с чем его едят?
              Какие существуют способы расширения возможностей прекомпиляции?
              Или это свой язык-компилятор писать, что для Qt и осуществлено?


              Qt решили что стандартного С++ им мало, и ввели ряд своих "спецификаторов". Типа сигнал, слот, коннект, дисконнект ... Все это достаточно удобно вливается в синтаксис обычного С++. Но после предкомпиляции MOC-ом (старая дока, но концепцию тянет) получается бог-весть-что. Но это работает, и весьма неплохо. Расширений "предкомпиляции" не существует, QT по сути авторитарно расширили спецификацию стандарта С++. (Кстати минус им - пользуются расширением файлов *.cpp незаконно! Сделали бы *.moc, вопросов бы не было)

              Цитата SectorbzC @
              И если так, то зачем? Если уже существует Obj C, где это реализовано?
              Не проще ли было воспользоваться возможностями Obj C?


              Qt - это "надстройка" над C++, Obj C - это "надстройка" над C. ИМХО, понятия близкие, но несовместимые. Хотя верю, если бы разработчики Qt решили за основной инструмент взять ANSI C, то к Obj C они бы и пришли. Но, увы, движение - параллельное.
                Цитата JoeUser @
                Разве нельзя создать нужную структуру в памяти и произвести приведение типов? ...
                О чём вопрос-то? Примерный ответ может быть такой: время жизни экземпляра класса начинается с момента возврата управления из его конструктора, поэтому нет вызова конструктора == нет объекта; и наоборот: создание "нужной структуры" подразумевает вызов и успешную отработку конструктора. Т.к. ни malloc(), ни realloc() о конструкторах ничего не знают, они не могут использоваться иначе нежели для предварительного резервирования региона памяти под объект, но не создания самого объекта. Исключение составляют только объекты с тривиальными конструкторами.
                Цитата JoeUser @
                ... Присвоить переменной адрес вручную созданной структуры?
                Использование объекта до начала его времени жизни есть неопределённое поведение. Из этого правила нет исключений. До того, как конструктор не приведёт в порядок отведённый под объект регион памяти, превратив мусор в нём в инвариантное состояние, работа с таким недообъектом сродни использованию неинициализированной переменной, только ещё хуже, ибо одно дело неопределённое значение переменной, итог операций с ней хотя бы можно предсказать, совсем другое неопределённое состояние объекта, реализация методов которого вообще говоря чёрный ящик.
                  Цитата Qraizer @
                  поэтому нет вызова конструктора == нет объекта; и наоборот: создание "нужной структуры" подразумевает вызов и успешную отработку конструктора.


                  Я накидал корявенький, но работающий пример - это тут. Глянь, пожалуйста.
                    JoeUser, работающий пример чего? Записи/чтения сырой памяти?
                      Цитата Kray74 @
                      JoeUser, работающий пример чего? Записи/чтения сырой памяти?

                      Ну да. Экземпляр класса "работающий" же? Понимаю, примитивно, но разве нельзя таким же образом инициализировать более сложные структуры, не прибегая к конструкторам?

                      Добавлено
                      Это я к тому, что, если зная секретную кухню std::string, можно и его попытаться таким же образом "сконструировать". Другой вопрос, что это нафик не нужно, но это уже другая песня.
                        to Kray74

                        Новую переменную?
                        Тогда добавить в структуру такой конструкт: (не проверял, но работать должно, т.е. технически это легко решаемо)
                        Скрытый текст
                        ExpandedWrap disabled
                          #include <iostream>
                           
                          #include <stdio.h>      /* printf, scanf, puts */
                          #include <stdlib.h>     /* realloc, free, exit, NULL */
                          #include <memory.h>     /* memset, memcpy */
                           
                          using namespace std;
                           
                          class T
                          {
                              struct Data
                              {
                                  int x; // по умолчанию
                                  float y;
                                  double z;
                                  char pch[32];
                           
                              ///
                                  short any_count;
                                  struct SAny
                                  {
                                      long id;
                                      intptr_t ptr;
                                  } * any_arr;
                              ///
                              } data_;
                           
                          public:
                              T ( T::Data * _newd_ = 0 )
                              {
                              /// по умолчанию
                                  data_ = (T::Data) { 15,87.f,150.f,"DefaultS", 0,0 };
                           
                              ///
                                  double * new_var = new double (365.563f);
                           
                                  T::Data::SAny new_any;
                                  new_any.id = 5; // t_list <double>::ID
                                  new_any.ptr = (intptr_t) new_var;
                           
                              /// по примеру: http://www.cplusplus.com/reference/cstdlib/realloc/
                                  Data::SAny * more = (T::Data::SAny*) realloc ( data_.any_arr, data_.any_count+1 * sizeof(T::Data::SAny) );
                                  if ( more )
                                  {
                                      data_.any_arr = more;
                                      data_.any_count++;
                                      data_.any_arr[data_.any_count-1] = new_any; /// КОПИРОВАНИЕ, а не...
                                  } /// else throw ex ("КАРАУЛ realloc НЕ СРАБОТАЛ", __FILE__,__LINE__);
                              ///
                           
                              /// если пользователь инициировал:
                                  if ( _newd_ ) data_ = (*_newd_);
                              }
                           
                              ~T()
                              {
                                  if ( data_.any_arr )
                                  {
                                      memset ( &data_.any_arr,0,data_.any_count * sizeof ( T::Data::SAny ) );
                                      free ( data_.any_arr );
                                  }
                                  memset ( &data_,0,sizeof ( T::Data ) );
                              }
                           
                          ///
                              template <class U>
                              void add ( U * _newvar_ )
                              {
                                  T::Data::SAny new_any;
                                  new_any.id = 10; // t_list <U>::ID
                                  new_any.ptr = (intptr_t) _newvar_;
                           
                              ///
                                  Data::SAny * more = (T::Data::SAny*) realloc ( data_.any_arr, data_.any_count+1 * sizeof(T::Data::SAny) );
                                  if ( more )
                                  {
                                      data_.any_arr = more;
                                      data_.any_count++;
                                      data_.any_arr[data_.any_count-1] = new_any;
                                  } /// else throw ex ("КАРАУЛ realloc НЕ СРАБОТАЛ", __FILE__,__LINE__);
                              ///
                              }
                          };
                           
                          int main()
                          {
                          /*
                          char any [ sizeof (std::string) ]; /// malloc( ... );
                          std::string * pstr = new (&any) std::string(); /// после этого any и pstr могут указывать на разные участки памяти,
                          /// учитывая "заголовки", табл вирт функ, размер типа, размер массива... всё может быть в заголовке объекта типа...
                          */
                              {
                                  T t;
                              }
                              cout << "Press ENTER to EXIT!" << endl;
                              cin.get();
                              return 0;
                          }


                        + эту SAny можно создать и вне типа, тогда бесящие двоеточия писать не нужно будет.
                        + SAny точно так же можно писать в std контейнер (т.к. не содержит С++ типов затруднений с выравниванием быть не должно, поэтому realloc).
                        + Там ещё необходимо предусмтреть доступ к элементу массива
                        - либо по enum,
                        - либо по строковому имени,
                        - либо по структуруе с id,строковым именем и т.д.,
                        - по "контрольной сумме" из строки (или как оно называется забыл уже, хэш-число)
                        - или ещё как-то.

                        to Qraizer

                        С помощью malloc и realloc можно (нужно же память выделить). Хотя выразился не математически корректно.

                        Но потребуется доп. помощь размещающего (placement) new
                        А вообще любой тип C++ можно представить как массив байт (и это, кстати, позволяет создать поток-БД (супераллокатор) с доступом к хранимому в "двоичной форме" элементу по ID типа + серийник экземпляра).
                        ExpandedWrap disabled
                          char any [ sizeof (std::string) ]; /// malloc( ... );
                          std::string * pstr = new (&any) std::string(); /// после этого any и pstr могут указывать на разные участки памяти,
                          /// учитывая "заголовки", табл вирт функ, размер типа, размер массива... всё может быть в заголовке объекта типа...


                        только после этого деструктор "вручную" вызывать придётся. (выравнивание не производится.)
                        Или освобождать память memset(). Вместо деструктора. - Что не даёт гаранти т.к. заголовок или табл вирт функ или ссылка на неё может записаться компиляторам куда угодно и это освобождено не будет. За корректное освобождение всего отвечает деструктор/delete.
                        Поэтому структуры Си можно создавать/освобождать методами Си. С++ лучше не стоит. Pod/no pod типы.

                        А тут: http://ideone.com/bpMQps

                        Это ряд ли. Т.к. невозможно учесть "размер заголовка" и "хвостики", который установит компилятор (разные компиляторы - разный заголовок + в заголовок объета может затесаться заголовок массива, который хранится в заголовке 1 объекта массива...)

                        Можно копировать с помощью = (знака равенства) или memcpy.
                        Но не всякий объект можно создать с помощью такого копирования (табл. вирт. функ, "особо изощрённые заголовки" и "дебаговые хвостики", "объекты созданные в конструкторе в динамич памяти" всё может потеряться при таком копировании, зависит от реализации в компиляторе). такой метод лучше применять к Си-сруктурам.
                        Да и с автоматич. вызовом деструктора что? Тоже не ясно.

                        Теоретически.

                        А насчёт DLL. Ну тут разное пишут. (Можно ли пользовать STL(или объекты C++) в DLL?) Т.е. STL нарушает ODR, получается.

                        to JoeUser

                        Понятно. Информации очень мало.
                        Сообщение отредактировано: SectorbzC -
                          Скажите, я правильно понимаю, что у SectorbzC просто приступ графомании, изобретения велосипедов с треугольными колёсами и ярко выраженное незнание плюсов, а остальные здесь "чисто для поржать"?
                            to MyNameIsIgor

                            Т.е. вы поняли предназначение ресурса как поржать над теми, кто меньше знает?
                            Я думаю, что вы поняли не правильно. Если действительно так поняли.
                            Но я могу ошибаться.
                            Сообщение отредактировано: SectorbzC -
                              Цитата JoeUser @
                              Цитата Kray74 @
                              JoeUser, работающий пример чего? Записи/чтения сырой памяти?

                              Ну да. Экземпляр класса "работающий" же? Понимаю, примитивно, но разве нельзя таким же образом инициализировать более сложные структуры, не прибегая к конструкторам?

                              Добавлено
                              Это я к тому, что, если зная секретную кухню std::string, можно и его попытаться таким же образом "сконструировать". Другой вопрос, что это нафик не нужно, но это уже другая песня.

                              Нет не работающий, согласно конструктору значение поля должно быть равно 10. У вас этот инвариант не соблюдается.

                              Зная секретную кухню конструктора, придется дублировать инициализацию в каждой точке создания объекта. Можно, конечно, но да, нафик не нужно.

                              Добавлено
                              Цитата SectorbzC @
                              Новую переменную?
                              Тогда добавить в структуру такой конструкт: (не проверял, но работать должно, т.е. технически это легко решаемо)

                              Напоминаю, что изначально вы задумывали сделать C++ более удобным (если я правильно понял). Приведенный конструкт как-то этой цели не способствует.
                              К тому же в C++ всегда была важна производительность, а у вас выделения динамической памяти при создании простейшего объекта.
                                Цитата JoeUser @
                                Экземпляр класса "работающий" же?
                                Нет. Тебе везёт, потому что ты воспользовался своими знаниями об особенностях конкретной реализации и чёрном ящике. В другой раз не повезёт, и выяснится это у клиента в Бразилии.

                                Добавлено
                                Цитата SectorbzC @
                                А вообще любой тип C++ можно представить как массив байт
                                Это верно только для standard-layout классов. Классы могут содержать свои состояния вне своего размещения (типичный пример – статические члены) или полагаться на характеристики исполнительного окружения (типичный пример – открытие файла в конструкторе и закрытие в деструкторе). Кроме того, некоторые аспекты состояния класса зависят от сторонних факторов, и их битовое представление неподконтрольно даже самому классу (типичный пример – хендл того самого открытого в конструкторе файла).
                                Цитата SectorbzC @
                                А насчёт DLL. ...
                                Все те пункты можно смело зачеркнуть и заменить моим кратким "нарушение ODR". Другое дело, что соблюсти ODR в системе, построенной на DLL, зачастую гораздо сложнее, чем на LIB, но это возможно при должном упорстве.

                                Добавлено
                                MyNameIsIgor, тема ярко выражена как холиварная. Но перетащить её туда я не могу, SectorbzC не сможет там писать, у него мало тематических сообщений.

                                Добавлено
                                Цитата Kray74 @
                                К тому же в C++ всегда была важна производительность...
                                Скорее принцип нулевой стоимости. Вот кстати да, как с этом у Objective C?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0671 ]   [ 16 queries used ]   [ Generated: 26.04.24, 04:12 GMT ]