Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегруженные оператори, Вопрос по <<, >> и декременту 
:(
    Опции темы
pr5erg1y
Дата 8.3.2012, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 3.3.2012

Репутация: нет
Всего: нет



Первое:
Вот перегружонный инкремент. Пробовал сделать декремент - не  получилось.
Подскажите как! 
Код

CVector & CVector::operator++ ()
{
    for(int i=0; i<this->size_v; ++i)
        this->vector[i]=this->vector[i]+1;

    return *this;
}


Второе:
Вот перегружонные cin и cout:
Код

istream& operator >> (istream&is, CVector & V)
{
    cout << "------------------------opetator >> ------------------\n\n";
    cout << "Enter Vector from " << V.GetSize() << " elements: \n";
    for(int i=0; i<V.GetSize(); ++i)
        is >> V.vector[i];
     return is; 
}

ostream& operator << (ostream& os, const CVector & V)
{
    cout << "------------------------opetator << ------------------\n\n";
    cout << "Vector is: \n";
    for(int i=0; i<V.GetSize(); ++i)
        os << "X = " << V.vector[i] << "\t\n"; 
    return os;
}


Все работает нормально.
Делаю через шаблоны:
Код

template <class T>
istream& operator >> (istream&is, CVector<T> & V)
{
    cout << "------------------------opetator >> ------------------\n";
    cout << "Enter Vector fron " << V.GetSize() << " elements: ";
    for(int i=0; i<V.GetSize(); ++i)
        is >> V.vector[i];
     return is; 
}

template <class T>
ostream& operator << (ostream& os, const CVector<T> & V)    
{
    cout << "------------------------opetator << ------------------\n";
    cout << "Vector is: /n";
    for(int i=0; i<V.GetSize(); ++i)
        os << "X = " << V.vector[i] << '\t'; 
    return os;
}


Выводит ошыбки:
1) warning LNK4042: объект указан более одного раза; лишние не учитываются
2) error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class CVector<double> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$CVector@N@@@Z) в функции _main
3) error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class CVector<double> &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$CVector@N@@@Z) в функции _main
4) fatal error LNK1120: 2 неразрешенных внешних элементов

Что я делаю не так? Жду помощи.
PM MAIL   Вверх
bsa
Дата 8.3.2012, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



реализация шаблонов должна быть ВО ВСЕХ ЕДИНИЦАХ КОМПИЛЯЦИИ, другими словами - в хидере. А ты, скорее всего, разместил в *.cpp.
Кстати, когда возникнут ошибки после переноса, воспользуйся ключевым словом inline.
PM   Вверх
Fynivx
Дата 10.3.2012, 01:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



В заголовке:
Код

template <class T>
ostream& operator << (ostream& os, const CVector<T> & V);


В коде класса:
Код

template <class T>
istream& operator >> (istream&is, CVector<T> & V)
{
    cout << "------------------------opetator >> ------------------\n";
    cout << "Enter Vector fron " << V.GetSize() << " elements: ";
    for(int i=0; i<V.GetSize(); ++i)
        is >> V.vector[i];
     return is; 
}
//Инстанцинирование необходимых операторов:
template istream& operator >><перегружаемый_тип_CVector_1> (istream&is, CVector<T> & V);
template istream& operator >><перегружаемый_тип_CVector_2> (istream&is, CVector<T> & V);
//...

//Возможно переопределение для некоторых классов:
template<>
istream& operator >><перегружаемый_тип_CVector_3> (istream&is, CVector<T> & V) {
    //здесь код для указанного типа
}
//...

И так далее по аналогии. Это должно избавить от ошибок линковки.
Но вряд ли избавит от первого варнинга. В чем там проблема - я не знаю. Но, скорее всего, что-то просто описано дважды.
PM MAIL   Вверх
bsa
Дата 10.3.2012, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Fynivx, так делать не надо, если ты не знаешь, зачем нужна такая возможность.
PM   Вверх
Fynivx
Дата 10.3.2012, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



bsa, инстанцинирование делает экземпляр шаблона для указанного класса. Это для того, чтобы избежать дублирования одного и того же кода, что получится, если, при полном описании в заголовке, в разных исходниках использовать шаблон с одним и тем же типом.

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


А второе - очень полезная штука тогда, когда некоторые типы, используемые в шаблоне, могут кардинально отличаться от остальных. Например, значения и указатели на значения.
PM MAIL   Вверх
bsa
Дата 10.3.2012, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Fynivx, подобное делают для выведения наиболее часто используемых типов шаблонов в отдельную библиотеку. Но это не отменяет необходимости включения полного кода шаблона во все единицы компиляции, в которых он используется. А дублирования кода в пределах одной цели не будет, так как спецификатор inline четко определяет, что невстраиваемый код будет только в единственном экземпляре в результирующем бинарнике.
PM   Вверх
Fynivx
Дата 10.3.2012, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



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

А инстанцинирование как раз отменяет необходимость реализации функции в каждой "единице компиляции", как вы выразились. Я пробовал. Честно. Оно для этого и придумано.
PM MAIL   Вверх
Fynivx
Дата 11.3.2012, 03:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



Рассматривал спецификации 11х плюсов и заметил - теперь, при реализации в хэдере или в нескольких файлах, там, где предполагается дублирование, для его избежания при инстанцинировании можно использовать спецификатор extern - как с переменными.
Код

extern template name<type>();

Но старый способ уж точно более элегантен.

PM MAIL   Вверх
mes
Дата 11.3.2012, 10:27 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(bsa @  10.3.2012,  16:58 Найти цитируемый пост)
 Но это не отменяет необходимости включения полного кода шаблона во все единицы компиляции, 

зачем требовать включать то, что не нужно ?

Цитата(Fynivx @  10.3.2012,  20:05 Найти цитируемый пост)
 вообще-то спецификатор inline работает с точностью до наоборот

мне кажется, bsa имел ввиду не дублирование кода, а дублирование определений..




--------------------
PM MAIL WWW   Вверх
bsa
Дата 11.3.2012, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Fynivx @  10.3.2012,  22:05 Найти цитируемый пост)
bsa, вообще-то спецификатор inline работает с точностью до наоборот - он говорит компилятору вставлять вместо вызова функции ее код везде, где она используется...
во-первых, он не "говорит", а "рекомендует" - компилятор сам решает, встраивать или нет. Так вот, на случай если компилятор решил не встраивать и существует "фича", что код невстроенной функции будет во всех объектных файлах, но при линковке останется только один экземпляр.

Цитата(Fynivx @  10.3.2012,  22:05 Найти цитируемый пост)
А инстанцинирование как раз отменяет необходимость реализации функции в каждой "единице компиляции", как вы выразились. Я пробовал. Честно. Оно для этого и придумано. 
Да. для этого и придумано. Но вот только где гарантии, что ты вместо int не захочешь использовать BigInt? Именно поэтому и нужен полный код шаблона.
Языки С/С++ позволяют многое, но очень часто из-за этой либеральности возникают серьезные проблемы.

PM   Вверх
Fynivx
Дата 11.3.2012, 18:32 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



Цитата(bsa @  11.3.2012,  14:28 Найти цитируемый пост)
существует "фича", что код невстроенной функции будет во всех объектных файлах, но при линковке останется только один экземпляр

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

А инстанцинирование необходимых шаблонов необходимо и является, как минимум, примером хорошего тона.

Реализация же чего-либо, размером больше строчки, в хедерах - симптом быдлокодинга, извините.

Это сообщение отредактировал(а) Fynivx - 11.3.2012, 18:44
PM MAIL   Вверх
volatile
Дата 11.3.2012, 20:36 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(Fynivx @  11.3.2012,  18:32 Найти цитируемый пост)
Реализация же чего-либо, размером больше строчки, в хедерах - симптом быдлокодинга, извините.

Тогда весь STL и пол-буста, попадают в это определение быдлокодинга. smile 

PM MAIL   Вверх
bsa
Дата 12.3.2012, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Fynivx @  11.3.2012,  19:32 Найти цитируемый пост)
Нет такой фичи. Просто встраиваемые функции в некоторых условиях можно переопределять, в связи с чем существует заблуждение, что они решают эту проблему. Вот и всё. Но если, по каким-то причинам, функция не будет встраиваемой (ведь, по-вашему, это возможно), во время линковки возникнет варнинг, подобный тому, что написан в начале поста. В лучшем случае.
ты видимо начитался книг (но не понял их) и считаешь себя гуру в С++. Но есть одна книга, на которую нужно ссылаться делая подобные утверждения - это стандарт языка С++.
Цитата
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline
specifier indicates to the implementation that inline substitution of the function body at the point of call
is to be preferred to the usual function call mechanism. An implementation is not required to perform this
inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules
for inline functions defined by 7.1.2 shall still be respected.
4 An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly
the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its
definition appears in the translation unit. — end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is
declared inline in one translation unit, it shall be declared inline in all translation units in which it appears;
no diagnostic is required. An inline function with external linkage shall have the same address in all
translation units
. A static local variable in an extern inline function always refers to the same object.
A string literal in the body of an extern inline function is the same object in different translation units.
[ Note: A string literal appearing in a default argument is not in the body of an inline function merely
because the expression is used in a function call from that inline function. — end note ] A type defined
within the body of an extern inline function is the same type in every translation unit.

Источник: ISO/IEC 14882:2011 Programming Language C++ - draft

Это сообщение отредактировал(а) bsa - 12.3.2012, 01:02
PM   Вверх
Fynivx
Дата 12.3.2012, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



bsa,
Я совершенно не считаю себя гуру.

А еще не понимаю, что из того, что там написано опровергает то, что написал я. Inline применяется для рекомендации а не для однозначного встраивания. С этим я затупил. Да.

Но второе абсолютно ничего не доказывает. Просто декларация inline автоматически внешней не сделается и, более того, реализация в заголовке не будет внешней нигде, где будет использоваться. А декларация, как внешней, 100% вызовет ошибку линковки, ибо символа нигде не будет.

Напомню, что для функций внешняя декларация - это прототип. Для шаблона - template<typename T>( args ) в месте реализации либо extern template<typename T>( args ) в любом месте кода.

Добавлено через 7 минут и 15 секунд
volatile
Ну, это отдельная тема) в STL просто нет другого выбора - они обязаны поддерживать пользовательские типы, как, впрочем, и , буст.
Другим способом этого сделать нельзя, к сожалению. И вряд-ли такая возможность появится в ближайшее время(
PM MAIL   Вверх
bsa
Дата 12.3.2012, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Fynivx @  12.3.2012,  18:09 Найти цитируемый пост)
Но второе абсолютно ничего не доказывает. Просто декларация inline автоматически внешней не сделается и, более того, реализация в заголовке не будет внешней нигде, где будет использоваться. А декларация, как внешней, 100% вызовет ошибку линковки, ибо символа нигде не будет.
когда ты делаешь определение шаблона в хидере, который подключаешь в нескольких единицах трансляции, то в каждой из этих единиц будет невстроенный экземпляр кода для этого шаблона (если он, конечно, в этом модуле используется). На этапе линковки лишние экземпляры будут отрезаны.
Если бы этого не было, то было бы нарушение стандарта.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0638 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.