The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
переменные параметры, !*! Dvorkin, 23-Мрт-02, 15:23  [смотреть все]
есть класс Buffer, в котором определена private переменная buf
class Buffer {
private buf;
....
}

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

Предполагаю слелать это следующим образом:
int Buffer::read( int _param, int ( *_reader)(...)) { ...... }
В ф-цию Buffer::read передается указатель на функцию чтения. Внутри ф-ции read мы имеем доступ к закрытым переменным класса и каким-то образом пихаем в ф-цию _reader эту переменную.

Можно ли так?
Если можно, то как?

WBR, Dvorkin

  • RE: переменные параметры, !*! Dvorkin, 15:24 , 23-Мрт-02 (1)
    >есть класс Buffer, в котором определена
    >private переменная buf
    >class Buffer {
    >private buf;
    >....
    >}
    >
    >Задача такая:
    >необходимо написать функцию чтения ( неважно,
    >откуда, например, из файла) непосредственно
    >в эту переменную. При этом
    >очень не хочется обьявлять новый
    >класс - читальщик, в котором
    >эта функция была бы дружественной
    >к классу Buffer.
    >
    >Предполагаю слелать это следующим образом:
    >int Buffer::read( int _param, int (
    >*_reader)(...)) { ...... }
    >В ф-цию Buffer::read передается указатель на
    >функцию чтения. Внутри ф-ции read
    >мы имеем доступ к закрытым
    >переменным класса и каким-то образом
    >пихаем в ф-цию _reader эту
    >переменную.
    >
    >Можно ли так?
    >Если можно, то как?
    >
    >WBR, Dvorkin

    Да, функция _reader имеет переменное число параметров.


    • RE: переменные параметры, !*! Арлекин, 10:36 , 24-Мрт-02 (2)
      >>есть класс Buffer, в котором определена
      >>private переменная buf

      Тип buf не указан - считаем его char*.

      >>class Buffer {
      >>private buf;
      >>....
      >>}
      ...
      >>int Buffer::read( int _param, int (
      >>*_reader)(...)) { ...... }
      >>В ф-цию Buffer::read передается указатель на
      >>функцию чтения.

      И buf и read являются членами класса Buffer.

      >>Внутри ф-ции read
      >>мы имеем доступ к закрытым

      Ну естественно.

      >>переменным класса и каким-то образом
      >>пихаем в ф-цию _reader эту
      >>переменную.

      И чем ЭТОТ ПОДХОД отличается от принципа друзей ?
      Только тем, что кроме buf'а твой reader ничего другого не увидит.

      >>
      >>Можно ли так?

      Почему же нет, только криво это, ИМХО( см. ЗЫЖ )

      >>Если можно, то как?
      >>

      Объяви функцию
      char* Buffer::getBufPrt() { return buf };
      например. После чего ты сможешь адрес переменной таскать куда хочешь и как хочешь. НО: ты сначала получишь вне класса указатель на его закрытый член, передашь его какой-то ф-ции чтения, потом указатель на ту функцию чтения будешь передавать в другой член класса. Бег по кругу.

      >>WBR, Dvorkin
      >
      >Да, функция _reader имеет переменное число
      >параметров.

      Не понял. Если не знаешь как сделать перерменное число параметров, читай man stdarg. В других случаях - объясни в чем проблема.

      ЗЫЖ
      Прежде всего я всегда имею класс работы с файлами. Делать его 10 минут, а пользоваться можно всегда. Но если идти по твоему пути я сделал бы так:
      В класссе Buffer:
      Buffer& operator << ( const char* str )
      {
         //Контроль размеров данных !
         ...
         //  
         buf[0] = 0;
         strcat( buf, str );
         return *this;
      }
      После чего извне класса Buffer можно писАть в эту переменную что угодно, и как тебе нравится:
      ...
      Buffer* ptrBuf = new Buffer...;
      const char aaa[] = "Test writing";
      ...
      ptrBuf << aa;
      ...
      При  таком подходе ты избавляешься от перетаскивания указателей - эти операции САМЫЕ опасные в С ибо указатели обладают очень неприятными свойствами: теряться и портиться - ,а все чтения из файла остаются вне класса и не путаются под ногами.


      • RE: переменные параметры, !*! Dvorkin, 11:19 , 25-Мрт-02 (3)
        hi!

        Мы не поняли друг друга.
        Есть класс Buffer, внутри которого переменная private: char *buf;
        Есть некоторые 2 функции ввода-вывода, про которых известно только что они возвращают число прочитанных или записанных байт и один из параметров каждой функции - Buffer.
        ==> Необходимо сделать общие функции Buffer::read/Buffer::write,
        которые принимали бы в качестве параметра указатель на функцию чтения, переменную Buffer (в/из которой читать/писать) и собственное переменное число других параметров. Так, как вызов делается внутри Buffer ==> эта функция чтения/записи может работать непосредственно с приватным указателем на char, который определен внутри Buffer.
        Проблема кроется вот в чем...
        1) как обнаружить среди параметров ф-ции Buffer::read переменную типа class Buffer и подсунуть вместо нее Buffer::buf (пусть этот параметр может быть только один) ?
        2) как взять все эти парамтры (c этой замененной переменной) и пихнуть их в вызов функции ввода вывода, указатель на которую передается.

        Код должен, по моему разумению, выглядеть примерно так:

        class Buffer {
        private:
        char *buf;
        int datalen;
        .....
        public:
        int read( int ( *_reader(...), ...)) {
           /* заменяем единственный параметр типа Buffer на Buffer::buf */
           /* делаем вызов ф-ции ввода/вывода: */
           int breaded = ( *_reader)( /* аргументы, переданные ф-ции Buffer::read с замененным параметром типа Buffer на Buffer::buf */);
           this->datalen += breaded;
           return( breaded);
        }

        }

        /* где многоточия - переменное число параметров. */

        Buffer buff;
        buff.read( &recv, sockfd, buff, 1024, options);
                                  ^^^^
        после чего имеем в буфере добавочку - полученную строку. :)
        Как раз мысль для того, чтобы не заниматься ненужными выделениями/копированиями памяти.
        А если делать как Вы предложили - функцию, возвращающую указатель на Buffer::buf, то это снимает идею защищенности данных.

        По всей видимости, тут необходимо выполнять операции непосредственно со стеком... Но ничего в явном виде не сказано ни в книжках, ни в мануале по stdarg.

        Есть мысли?

        WBR, Dvorkin
        -----------------------------------------------
        >>>есть класс Buffer, в котором определена
        >>>private переменная buf
        >
        >Тип buf не указан - считаем
        >его char*.
        >
        >>>class Buffer {
        >>>private buf;
        >>>....
        >>>}
        >...
        >>>int Buffer::read( int _param, int (
        >>>*_reader)(...)) { ...... }
        >>>В ф-цию Buffer::read передается указатель на
        >>>функцию чтения.
        >
        >И buf и read являются членами
        >класса Buffer.
        >
        >>>Внутри ф-ции read
        >>>мы имеем доступ к закрытым
        >
        >Ну естественно.
        >
        >>>переменным класса и каким-то образом
        >>>пихаем в ф-цию _reader эту
        >>>переменную.
        >
        >И чем ЭТОТ ПОДХОД отличается от
        >принципа друзей ?
        >Только тем, что кроме buf'а твой
        >reader ничего другого не увидит.
        >
        >
        >>>
        >>>Можно ли так?
        >
        >Почему же нет, только криво это,
        >ИМХО( см. ЗЫЖ )
        >
        >>>Если можно, то как?
        >>>
        >
        >Объяви функцию
        >char* Buffer::getBufPrt() { return buf };
        >
        >например. После чего ты сможешь адрес
        >переменной таскать куда хочешь и
        >как хочешь. НО: ты сначала
        >получишь вне класса указатель на
        >его закрытый член, передашь его
        >какой-то ф-ции чтения, потом указатель
        >на ту функцию чтения будешь
        >передавать в другой член класса.
        >Бег по кругу.
        >
        >>>WBR, Dvorkin
        >>
        >>Да, функция _reader имеет переменное число
        >>параметров.
        >
        >Не понял. Если не знаешь как
        >сделать перерменное число параметров, читай
        >man stdarg. В других случаях
        >- объясни в чем проблема.
        >
        >
        >ЗЫЖ
        >Прежде всего я всегда имею класс
        >работы с файлами. Делать его
        >10 минут, а пользоваться можно
        >всегда. Но если идти по
        >твоему пути я сделал бы
        >так:
        >В класссе Buffer:
        >Buffer& operator << ( const char*
        >str )
        >{
        >   //Контроль размеров данных
        >!
        >   ...
        >   //
        >   buf[0] = 0;
        >
        >   strcat( buf, str
        >);
        >   return *this;
        >}
        >После чего извне класса Buffer можно
        >писАть в эту переменную что
        >угодно, и как тебе нравится:
        >
        >...
        >Buffer* ptrBuf = new Buffer...;
        >const char aaa[] = "Test writing";
        >
        >...
        >ptrBuf << aa;
        >...
        >При  таком подходе ты избавляешься
        >от перетаскивания указателей - эти
        >операции САМЫЕ опасные в С
        >ибо указатели обладают очень неприятными
        >свойствами: теряться и портиться -
        >,а все чтения из файла
        >остаются вне класса и не
        >путаются под ногами.

        • RE: переменные параметры, !*! Арлекин, 11:35 , 25-Мрт-02 (4)
          >А если делать как Вы предложили - функцию, возвращающую указатель на Buffer::buf, то это снимает идею защищенности данных.

          Как раз ЭТО я и не предлагал. ЭТО был вариант реализации ВАШЕЙ идеи. Я предлагал перегрузить оператор "<<" для занесения даных в буфер.

          >
          >По всей видимости, тут необходимо выполнять
          >операции непосредственно со стеком... Но
          >ничего в явном виде не
          >сказано ни в книжках, ни
          >в мануале по stdarg.
          >
          Именно, в man stdarg и описывается действие макрокоманд
          ...
               va_list pvar;

               void va_start(va_list pvar, void parmN);

               (type *) va_arg(va_list pvar, type);

               void va_copy(va_list dest, va_list src);

               void va_end(va_list pvar);
          ....
          Параметры функции передаются через стек и работа с адресами параметсров и есть работа со стеком. На русском эта байда хорошо описана у Чана.
          Можно также глянуть man va_start etc.

          >Есть мысли?

          Если коротко - класс сокетов должен быть базовым для классов буферов, протоколов представления и пр. А функция чтения/записи из/в сокет(а) объявляется виртуальной, после чего каждый порожденный класс может ее переопределять по-своему.
          ЗЫ
          Я не сторонник программирования ради искусства, но ИМХО, в д.с. множественное наследование С++ как раз то что требуется.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру