#c #pointers #reference #operator-overloading #overload-resolution
#c #указатели #ссылка #перегрузка оператора #перегрузка-разрешение
Вопрос:
Я работаю над назначением, в котором я должен перегрузить оператор вставки, чтобы получить объект Node. Я создал функцию перегрузки оператора вне определения класса, но внутри файла node.h. Все компилируется нормально, но перегруженный оператор не вызывается, вместо этого я получаю простой адрес объекта.
Мне запрещено изменять вызывающий код, поэтому любые изменения должны касаться перегрузки оператора.
Мой код в его нынешнем виде прямо сейчас:
/** OPERATOR << ***********************************/
template<class T>
inline std::ostream amp; operator << (std::ostream amp; out, const Node <T> *amp; pHead)
{
out << "INCOMPLETE";
return out;
}
Прямо сейчас я просто хочу убедиться, что вызван перегруженный оператор. Я исправлю выходной код, как только буду уверен, что вызываю правильный оператор.
Вызывающий код:
// create
Node <char> * n = NULL;
// code modifying n
// display
cout << "t{ " << n << " }n";
Комментарии:
1.
cout << *n;
было бы более простым решением2. Это верно, но, как указано, я не могу изменить вызывающий код.
3. извините, пропустил эту часть.
4. не очень уверен, возможно, удаление amp; в
const Node <T> *amp;
сработает, или вы также можете предоставить неконстантную версию.
Ответ №1:
Обратите внимание, что тип параметра pHead
является ссылкой на неконстантный, const Node<T>*
является неконстантным указателем на const, тип аргумента n
является Node<T>*
(т. е. неконстантным указателем на неконстантный). Их тип не совпадает, Node<T>*
необходимо преобразовать в const Node<T>*
, который является временным и не может быть привязан к ссылке на неконстантный.
Короче говоря, вы не можете привязать ссылку на неконстантный объект к объекту с другим типом.
Но ссылка на const может быть привязана к temporary, поэтому вы можете изменить тип параметра на ссылку на const:
template<class T>
inline std::ostream amp; operator << (std::ostream amp; out, const Node <T> * const amp; pHead)
// ~~~~~
Или измените его на передаваемый по значению, Node<T>*
будет неявно преобразован в const Node<T>*
при передаче в качестве аргумента. (Передача указателя по ссылке на const не имеет особого смысла.)
template<class T>
inline std::ostream amp; operator << (std::ostream amp; out, const Node <T> * pHead)
Наконец, перегрузка operator<<
типом указателя выглядит странно. Наиболее распространенной формой с пользовательским типом будет:
template<class T>
std::ostream amp; operator << (std::ostream amp; out, const Node <T> amp; pHead)
Комментарии:
1. Благодарим вас за разъяснение деталей использования const и ссылочных типов. Я начал с последнего блока кода, но модератор класса сообщил мне, что ему необходимо принять указатель. Первый опубликованный вами блок кода отлично работает (во всяком случае, для этого назначения.) Я буду помнить о ваших рекомендациях в дальнейшем.
Ответ №2:
Проблема в том, что средство вставки принимает параметр типа const Node<T>*
, но он вызывается с аргументом типа Node<T>*
; преобразование из T*
в const T*
не выполняется. Итак, «исправление» заключается в удалении const
из средства вставки потока.
Но, как намекнуто в комментарии, наличие средства вставки, которое принимает указатель на тип, является плохой идеей. Это должно занять const Node<T>amp;
, как и у всех других вставщиков в мире. Я понимаю, что это ограничение, налагаемое присваиванием; если это так, то это идиотизм. Тебя плохо учат.
Комментарии:
1. Вы правы в том, что это ограничение класса. В курсе мы создаем класс Node и некоторые независимые функции. На следующей неделе мы берем класс Node и эти функции и объединяем их в класс с двойной связью List. До сих пор (5 недель) все другие структуры данных использовали указанный вами общий метод. Я полагаю, что на этой неделе все по-другому, потому что класс Node не является полным абстрактным типом данных.