На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> указатель на функцию-элемент класса... , или адрес функции-элемента класса. не получается.
    Подскажите, пожалуйста, как разобраться с проблемкой в программе:
    Решил попробовать использовать классы С++ и наткнулся вот на какую ситуацию.
    у меня есть два класса. в одном описан элемент-функция. во втором - элемент-указатель на функцию.
    Хочется присвоить указателю адрес этой функции-элемента, а не получается. Вот если указателю
    подсунуть "просто функцию", вне класса - всё нормально.
    Для иллюстрации набросал вот такой примерчик:

    ExpandedWrap disabled
      //--------------------
      class class_a
      {
        public:
          char (*fptr)(char);
      };
       
      //--------------------
      class class_b
      {
        public:
          char f(char);
      };
       
      //-------------------
      char class_b::f(char)
      {
        return '!';
      }
       
      //-------------------
      char f2(char)
      {
        return '~';
      }
       
      //-------------------
      int main()
      {
        class_a a;
        class_b b;
        
        a.fptr = f2;
      //  a.fptr = b.f;       // Error[Pe300]: a pointer to a bound function may only be used to call the
                                  //function
      //  a.fptr = class_b::f;// Error[Pe513]: a value of type "char (__code class_b::*)(char)" cannot be
                                  //assigned to an entity of type "char (*)(char)"
        
        return 0;
      }


    вот f2, функция "сама по себе", нормально присваивается. а на закомментированные строчки
    компилятор ругается. как правильно надо? Просьба гнилыми помидорами не забрасывать :).

    ЗЫ. компилятор используется IAR 3.21, но стандарты языка везде одинаковы...
    Сообщение отредактировано: trainer -
      Предположение - сделать метод в классе B, который будет возвращать указатель на функцию class_b::f, и вызывать этот метод из класса class_a?
        Цитата //nikson @
        // a.fptr = b.f; // Error

        Или делай свою функцию в class_b статической, или используй тип (class_b::*)(char) в качестве указателя на функцию.
          Цитата //nikson @
          вот f2, функция "сама по себе", нормально присваивается. а на закомментированные строчки
          компилятор ругается. как правильно надо? Просьба гнилыми помидорами не забрасывать

          Все дело в том, что указатель на функцию-член - далеко не тоже самое, что указатель на свободную функцию. Вот компилятор и ругается. Я бы предложил сделать так:

          ExpandedWrap disabled
            //--------------------
            class class_a
            {
              public:
                boost::function<char (char)> fptr;
            };
             
            //--------------------
            class class_b
            {
              public:
                char f(char);
            };
            //...
            //...
            int main()
            {
              class_a a;
              class_b b;
              
              a.fptr = boost::bind(&b::f, &b, _1);
              a.fptr('A');
              
              return 0;
            }
            ExpandedWrap disabled
              class MyClass{
                  typedef long ( MyClass::* FPTR )( int );
               
                public:
                  long func( int a ){ return ++a; }
                  long func( int a, char b ){ return a += b; }
               
               
                  void anyfunc( FPTR function, int a ){
                    a = (this->*function)( a );
                  }
               
                  void runfunc(){
                    anyfunc( &MyClass::func, 5 );
                  }
              };
              ExpandedWrap disabled
                //--------------------
                class class_b
                {
                  public:
                    char f(char);
                };
                 
                //-------------------
                char class_b::f(char)
                {
                  return '!';
                }
                 
                class class_a
                {
                  public:
                  char (class_b::*fptr)(char);
                };
                 
                //-------------------
                int main()
                {
                  class_a a;
                  class_b b;
                  
                  a.fptr = &class_b::f;
                 
                  (b.*a.fptr)('a');
                  
                  return 0;
                }
                Большое спасибо всем ответившим!

                Несколько комментариев, зачем такое понадобилось. Программа предназначена для микроконтроллера, у прибора будет ЖКИ, и необходимо обеспечить графический интерфейс с пользователем. Для этого решил сделать набор простеньких классов а-ля Билдер - кнопочки, надписи итд. Получается, в программе есть *чисто программные* блоки (те самые графические элементы), а есть аппаратно-зависимые (работа с памятью, клавиатурой итд итп). Логично было бы их разделить. В самом деле, например, классу _надпись_ при отрисовке совершенно не надо знать, откуда и каким образом берётся массив байт с изображением (в разных устройствах может же быть по-разному) - ему просто подавай функцию, которая на заданный символ вернёт указатель на буфер (а сама реализует связь с памятью, обмен данными итд). Вот такую функцию я сделал в классе _микросхема_памяти_, образно говоря. При попытке подсунуть её классу _надпись_ и возник вопрос :)

                Поэтому наиболее подходящий вариант от Flex Ferrum с использованием boost:: - почитал доки - вроде бы в самый раз будет. Если удастся это использовать и код особо не увеличится в размерах - будет просто супер!

                В принципе, можно попробовать сделать статическую функцию, но как это повлияет на работу - надо будет ещё подумать.

                Ну, а использовать внутри класса с указателем хоть какое-нибудь упоминание о другом классе (напр, в типе указателя) не хотелось бы - нарушается принцип независмости, из-за которого всё это и было затеяно.

                ЗЫ. тему не закрываю, а вдруг с boost сам не разберусь, тогда ещё поспрашиваю :)
                  boost в мелкоконтроллере - довольно смело. :)
                    Цитата trainer @
                    boost в мелкоконтроллере - довольно смело.

                    Я думаю, от компилятора зависит. bind/function разворачиваются оптимизатором очень даже неплохо.
                      Там(в function) исключения вроде используются, а в них - std::string.
                        Цитата //nikson @
                        В принципе, можно попробовать сделать статическую функцию, но как это повлияет на работу - надо будет ещё подумать.

                        Дык всё зависит от того, что ты хочешь сделать. Если твоя функция class_b::f работает с данными уже существующего объекта типа class_b, то тогда её не надо делать статической. Если же тебе нужен просто аналог глобальной функции с правом доступа к закрытым членам объектов типа class_b, используемых где-то внутри этой функции, либо ты просто хочешь выразить принадлежность этой функции к данном классу (хотя по сути её можно было бы сделать глобальной), то тогда следует использовать статическую функцию. Наконец, может ты вообще захотел сгруппировать глобальные функции в некую именованную совокупность, но тогда для этого лучше подходит пространство имён, а не класс.

                        P.S. С бустом с таким знанием языка работать не советую :-‎)
                          Цитата //nikson, 19.07.2006, 2:37:59, 1182897
                          ЗЫ. компилятор используется IAR 3.21, но стандарты языка везде одинаковы...

                          под какой контроллер?
                          при описание класса IAR сожрал много памяти (работали с ATMeag8) :yes:
                            Цитата
                            под какой контроллер?


                            msp430f149. на борту 60кб - пока ещё место есть :)
                              Ой... а чем для контроллера Си не устаривает? ИМХО для таких целей Си куда более пригоден, чем Си++.
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0.0978 ]   [ 16 queries used ]   [ Generated: 26.04.26, 19:28 GMT ]