Объявляя * оператором друга, , вы указываете компилятору искать функцию
ostream& operator<<(ostream &,T);
, где T
- это тот же тип, для которого создан шаблон класса btree.(например, для btree<Node>
фактическая подпись будет ostream& operator<<(ostream &, Node);
- при условии, что у вас есть члены i
и n
типа Node
)
Эта функция будет иметь доступ к закрытым и защищенным членам(переменные и функции) класса btree<T>
для всех экземпляров T
, но на самом деле он не является членом класса (как это было бы без ключевого слова friend
).
Оператор определение , которое вы предоставляете, предназначено для оператора, который является членом класса шаблона btree, как если бы у вас было объявлено
template<class T>
class btree
{
public:
ostream& operator<<(ostream &,T);
};
Это связано с btree<T>::
префикс, который вы включили (который указывает, к какому классу принадлежит функция / оператор).
Так как в классе нет соответствующего оператора объявление (см. приведенное выше описание объявления друга),компилятор жалуется.
Чтобы это исправить, вы либо
- оставляете друга декларацию , удаляете префикс
btree<T>::
и template<class T>
из оператора определение и изменитьВторой тип параметра - btree<Type>&
, где Type
- это один из типов, с которым вы ожидаете, что шаблон btree будет создан (например, Node
), - затем предоставьте аналогичные определения и для других таких типов.. - или удалите ключевое слово
friend
из объявления в классе и удалите параметр T
как из объявления , так и из определения , так как теперь предполагается, что оператор работает на всем btree (которое неявно предоставляется через *this
). - В качестве альтернативы, вы можете поэкспериментировать с объявлением оператора друга в качестве шаблона, но для этого требуется еще немногоизменения: (подробнее о предварительное объявление )
template<class T> btree; // forward declaration of class btree
// forward declare operator (or move definition here)
template<class T>
ostream& operator<<(ostream &o, btree<T>& s);
// declare operator as template friend
template<class T>
class btree
{
public:
friend ostream& operator<< <> (ostream &, bree<T>&);
// note <> after operator name to denote template with no new template parameters
};
Обратите внимание, что выше Я предполагал, что вы хотите вывести все дерево (то есть вызов operator<<
для объекта btree).Из имеющегося у вас кода неясно, является ли это вашим намерением (класс btree не имеет членов i
и n
). Если не , а тип, для которого вы хотите вызвать оператор <<
, является фактическим параметром шаблона btree, то вам не нужно изменять второй параметр шаблонного оператора с T
,но также нет необходимости объявлять его как friend
класса btree, поскольку оператор не зависит от btree.Вам необходимо объявить его другом класса, члены которого i
и n
, к которым вы обращаетесь в определении оператора (например, Узел выше), если i
и / или n
является частным в этом классе.Понятие о потере btree<T>::
(или Node::
) по-прежнему применимо, поскольку оператор не принадлежит ни к какому классу.
Соедините еще несколько вещей, предполагая, что вы пойдете с объявлением друга:
- Тип второго параметра для оператора должен быть
btree<T>&
(с акцентом на &
), так как более эффективно передать ссылку объекту btree, чем копировать все btree (илиповерхностная копия, если вы используете указатели и используете стандартный копировальный -9696 *) - , второй параметр также должен быть помечен
const
, поскольку (предположительно) вы не хотите изменятьbtree объект во время вывода.Помните, что в этом случае вам нужно будет пометить некоторые неизменяемые методы в btree<T>
как const
, чтобы разрешить его компиляцию.(См. Часто задаваемые вопросы по const правильности )
ПРАВИТЬ несколько раз, чтобы прояснить и убедиться в правильности