реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Проблема с inline членом класса, WinAVR-20080610
kurtis
сообщение Oct 28 2008, 16:23
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Есть несколько классов, используются для вывода на экран ЖКИ. Смысл их заключается в том что в коде я могу написать что-то вроде такого
Цитата
unsigned short myInt = 123;
short mySignedInt = -765;
float myFloat = 123.43;

LCD << InitScr() << myInt << ',' << mySignedInt << ',' << myFloat << myString;
И оно будет работать, т.е. мне не нужна отдельная функция для вывода на экран элемента каждого типа. Но возникает необходимость в определённых служебных операциях, например по умолчанию числа выводятся в десятичной системе, а мне нужно чтоб выводилось в шестнадцатеричной и т.д. В Си++ для "больших" компьютеров, в подобных ситуациях, используются манипуляторы ввода-вывода. Я попытался сделать здесь тоже самое. В приведённом выше примере, InitScr() - подобие манипулятора, т.е. ничего не выводит, но выполняет определённые служебные функции.
Есть основной класс C_Lcd, где выполняется перегрузка оператора << для всех основных используемых типов. Виртуальный класс ILcdManipulator и класс InitScr, который выполняет роль манипулятора, вызывая функцию LcdScreenInitialization() класса C_Lcd.
Проблема возникает при описании функции LcdScreenInitialization(). Когда я ее описую в самом классе, например
Код
void LcdScreenInitialization()
{
    PositionX = 0;
}
то работает все отлично, но когда я определяю ее за пределами класса как inline
Код
inline
void С_Lcd::LcdScreenInitialization()
{
    PositionX = 0;
}
то компилятор выдает ошибку
Цитата
obj/Test.o: In function `InitScr::operator<<(C_Lcd&) const':
D:\PROJECT_M\mPDZ2\Section1\UP\Slave4\Project/class/LCD.h:70: undefined reference to `C_Lcd::LcdScreenInitialization()'
причем, если я убираю слово inline, то ошибка пропадает, но увеличивается объем памяти занимаемый программой, приблизительно на 25 байт за каждое использование InitScr() в программе.
Вопрос! Почему при описании функции за пределами класса, с использованием ключевого слова inline, компилятор выдает ошибку, хотя вроде я ничего криминального не делаю?

З.Ы. На компютере, вариант с внешних описанием и inline'ом, компилируется без ошибок.

Вот сам код описание классов.
Код
class C_Lcd;

class ILcdManipulator
{
    public:
        virtual ~ILcdManipulator() {};
        virtual C_Lcd & operator << ( C_Lcd & out ) const = 0;
};

class C_Lcd
{
    private:
        unsigned char PositionX;   //Текущая позиция курсора по горизонтали [0..16(20)]
    public:
        C_Lcd& operator << ( const char * );
        C_Lcd& operator << ( unsigned short );
        C_Lcd& operator << ( short );
        C_Lcd& operator << ( const ILcdManipulator& Manipulator )
        {
            return Manipulator.operator << (*this);
        };

        void LcdScreenInitialization();

        C_Lcd ( void ) {
            // Periphs::UART0.Init();
        }
};

class InitScr : public ILcdManipulator
{
    public:
        virtual C_Lcd & operator << (C_Lcd& out) const {
            out.LcdScreenInitialization();
            return out;
        };
};
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 28 2008, 16:35
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(kurtis @ Oct 28 2008, 19:23) *
Почему при описании функции за пределами класса, с использованием ключевого слова inline, компилятор выдает ошибку, хотя вроде я ничего криминального не делаю?
А в классе эта функция тоже описана как inline?
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Oct 28 2008, 16:38
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Я бы две вещи попробывал:

1. В описании класса написать :
Код
inline void LcdScreenInitialization();


2. Еще лучше и надежнее :
Код
void LcdScreenInitialization() {PositionX = 0;}


Да хочется лишний раз отметить, что многие авторы неоднократно писали (и это так и есть), что компилятор не обязан делать функцию inline, если по каким-то своим соображением так считает.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 28 2008, 16:55
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(kurtis @ Oct 28 2008, 19:23) *
но когда я определяю ее за пределами класса как inline
1) В каком месте "за пределами класса"? Если в .cpp файле, после места использования или вообще в другом .cpp относительно места использования - то так и будет. Надо чтобы компилятор "увидел" тело функции до того, как встретит точку встраивания.
2) GCC хочет, чтобы inline было в декларации функции в классе.
3) чтобы GCC не умничал, а всегда делал встраивание, перед inline надо добавить __attribute__(("always_inline"))


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kurtis
сообщение Oct 28 2008, 17:19
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Все, до меня дошло!!! 1111493779.gif
Нужно тело inline-функции добавить в .h файл, с описанием класса.
Спасибо за ответы, а то б еще долго "думал"...
Go to the top of the page
 
+Quote Post
vik0
сообщение Oct 28 2008, 17:23
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Цитата(kurtis @ Oct 28 2008, 19:08) *
//это файл LCD.cpp

А как компилятор/компоновщик увидит вашу inline функцию, если она реализована в .cpp файле? Это отдельная "единица трансляции". Выносите вашу реализацию в заголовочный файл.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 22:47
Рейтинг@Mail.ru


Страница сгенерированна за 0.01428 секунд с 7
ELECTRONIX ©2004-2016