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