Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: inline методы классов
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
koluna
Здравствуйте!

WinAVR.
Пишем класс. Большинство его методов очень простые и маленькие. Хотим сделать эти методы inline.
Причём класс ДОЛЖЕН БЫТЬ описан в .h файле, а реализация методов ДОЛЖНА БЫТЬ ВЫПОЛНЕНА в .cpp файле. Не спрашивайте почему wink.gif
Т. е., трудность - разделение описания класса и определения его inline методов на два файла.

Код ниже - правильная реализация inline методов класса?
Может быть они должны быть реализованы или строго в теле класса (по-умолчанию уже inline) или вне класса, но с указанием спецификатора доступа и обязательно в .h файле?

qwe.h
Код
class qwe
{
   public:
      inline void f(void);
};


qwe.cpp
Код
void qwe::f(void)
{
// что-то
};


Благодарю заранее!
IgorKossak
Цитата(n_bogoyavlensky @ May 28 2009, 15:15) *
Может быть они должны быть реализованы или строго в теле класса (по-умолчанию уже inline) или вне класса, но с указанием спецификатора доступа и обязательно в .h файле?

Именно так, в одном файле.
koluna
Цитата(IgorKossak @ May 28 2009, 15:24) *
Именно так, в одном файле.


Почему?
IgorKossak
Цитата(n_bogoyavlensky @ May 28 2009, 15:26) *
Почему?

Потому, что при компиляции любого *.c\*.cpp файла, в который включен Ваш *.h файл, должна быть видна реализация inline функции. Ведь inline подразумевает вставку в код именно тела функции, а не её вызов.
Harbour
Страуструп: "Чтобы реализация вызова подстановкой стала возможна даже для не слишком развитых систем программирования, нужно, чтобы не только определение, но и описание функции-подстановки находилось в текущей области видимости. В остальном спецификация inline не влияет на семантику вызова."

inline - это только hint компилятору. в случае определения функции где-то вовне, он ее не видит - следовательно не знает ее размер и не может сгенерить ее как inline, посему вставляет стандартный call
HARMHARM
В принципе, простой класс вообще может быть целиком описан в .h файле. Впрочем, практика на любителя.
Еще имейте в виду - компилятор обычно инлайнит только очень короткие функции, вроде такой:
Код
    inline unsigned int getUsedCount( void )
    {
        return qty;
    }

Функции подлиннее делает вызываемыми, причем уже в конкретном объекте компиляции, если объектов несколько, функция будет в каждом...
Тут, конечно, много зависит от компилятора и его настроек. Возможно, придется пользоваться директивами вроде
Код
#pragma inline=forced
Сергей Борщ
Цитата(HARMHARM @ May 29 2009, 01:17) *
если объектов несколько, функция будет в каждом...
на этапе компиляции. На этапе линковки останется только один экземпляр - ибо все копии этой функции имеют одно и то же имя. Аналогичный (а может и этот же) механизм действует при инстанцировании шаблонов.
HARMHARM
Цитата(Сергей Борщ @ May 29 2009, 01:31) *
на этапе компиляции. На этапе линковки останется только один экземпляр - ибо все копии этой функции имеют одно и то же имя. Аналогичный (а может и этот же) механизм действует при инстанцировании шаблонов.

Точно! Не заметил, спасибо! rolleyes.gif
Не совсем понятно, почему линкер не ругается на одинаковые символы в этом случае? Подозреваю, что играют роль ? или ?? в начале названия метки, как и в ?cstartup... (IAR)
Сергей Борщ
Цитата(HARMHARM @ May 29 2009, 06:54) *
Не совсем понятно, почему линкер не ругается на одинаковые символы в этом случае?
Потому что их имена экспортируются не директивой PUBLIC, а директивой PUBWEAK (можно почитать в описани на ассемблер), которая как раз для таких случаев и придумана. Ну или компилятор генерит аналогичные признаки в объектном коде. Еще одно применение этой директивы, которым вы наверняка пользуетесь - putchar(). Библиотечный экспортируется с PUBWEAK (это видно, если посмотреть список символов библиотеки при помощи xlib), а ваш - с PUBLIC.
alx2
Цитата(n_bogoyavlensky @ May 28 2009, 17:15) *
Причём класс ДОЛЖЕН БЫТЬ описан в .h файле, а реализация методов ДОЛЖНА БЫТЬ ВЫПОЛНЕНА в .cpp файле.
Что подразумевается под словом "описан"? Forward declaration под это понятие подпадает? Если да, то в .h файле можно написать "class qwe;", а в .cpp файле - его полное определение:
Код
class qwe {
public:
  void f(void) { /* что-то */ }
};
sergeeff
Про inline уже неоднократно писалось на форуме.
1. Даже если написано inline - это не значит, что компилятор сделает функцию как inline.
2. Если желаете, чтобы функция, объявленная как inline, с большей вероятностью стала такой - она должна быть описана в .h файле.
3. Если функция в .h декларирована как inline, а описана в .cpp (даже если и inline) она везде будет вызываться как обычная функция.
Сергей Борщ
Цитата(sergeeff @ May 29 2009, 18:17) *
3. Если функция в .h декларирована как inline, а описана в .cpp (даже если и inline) она везде будет вызываться как обычная функция.
как интересно.
Код
file.h
class a_t
{
public:
    inline void test();
}
#ifdef IN_HEADER
void a_t::test()
{
}
#endif

file.cpp:

#include "file.h"
#ifndef IN_HEADER
void a_t::test()
{
}
#endif
a_t a;
void Test()
{
    a.test();
}
компилятор для file.cpp не заметит отличий.
sergeeff
Ну да, правильнее сказать, что везде, кроме самого модуля (file.cpp, например), где inline функция описана.
HARMHARM
Немножечко офф.
Цитата(Сергей Борщ @ May 29 2009, 14:09) *
Еще одно применение этой директивы, которым вы наверняка пользуетесь - putchar().

Я не использую putchar, вместо этого сделал свой sprintf с промежуточным буфером. Вопрос такой - будет ли эффективнее вариант с printf/putchar с той точки зрения что нет расхода памяти на буфер?
sergeeff
Цитата(HARMHARM @ May 30 2009, 12:58) *
Немножечко офф.

Я не использую putchar, вместо этого сделал свой sprintf с промежуточным буфером. Вопрос такой - будет ли эффективнее вариант с printf/putchar с той точки зрения что нет расхода памяти на буфер?


Вопрос в том, что для вас эффективность. Плюс к тому, при выводе в буфер есть проблема его потенциального переполнения.
HARMHARM
Цитата(sergeeff @ May 30 2009, 14:22) *
Вопрос в том, что для вас эффективность. Плюс к тому, при выводе в буфер есть проблема его потенциального переполнения.

В данном случае эффективность по памяти, как я и написал.
Естественно, использую vsnprintf, спасибо.
sergeeff
Сами же и отвечаете на поставленный вопрос. Эффективность - минимум используемой памяти? Тогда лишний буфер - потеря этой эффективности.
Сергей Борщ
Цитата(HARMHARM @ May 30 2009, 12:58) *
будет ли эффективнее вариант с printf/putchar с той точки зрения что нет расхода памяти на буфер?
Думаю, что будет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.