【问题标题】:C++ overloading operator+ using a class and a int parameter as template使用类和 int 参数作为模板的 C++ 重载运算符
【发布时间】:2020-01-09 23:16:25
【问题描述】:

我不知道这段代码有什么问题:

template <class T = char, int num = 100> class Stack;
template <class T = char, int num1 = 100, int num2 = 100> Stack<T, num1>& operator+=(Stack<T, num1>& s1, const Stack<T, num2>& s2);
template <class T, int num>
class Stack{
template <T, int num1, int num2 > friend  Stack<T, num1>& operator+=(Stack<T, num1>& s1, const Stack<T, num2>& s2);
public:
   ...
private:
   Entry* first;
   class Entry{
      ...
   }
   void append(const Stack& s){
        if(isEmpty()) first = &s;
        else first->last().next = &s;
   }
   ...
};
template <class T, int num1, int num2>
Stack<T, num1>& operator+=(Stack<T, num1>& s1, const Stack<T, num2>& s2){
    s1.append(Stack<T, num2>(s2));
    ...
};

关键是我已经将班级的友谊设置为运营商,我仍然收到error: 'append' is a private member of 'Stack&lt;char, 100&gt;'所以我做错了什么,有人可以检查一下吗?

【问题讨论】:

  • 考虑让operator+ 成为Stack 类的非静态成员,然后它可以访问append() 而无需成为friend。就此而言,为什么不直接将append() 逻辑移动到operator+ 中呢?或者更好的是,将operator+= 添加到Stack 类,然后让operator+(成员或其他成员)调用operator+=。拥有私人append() 真的没有意义
  • auto z = x + y;会修改x是不寻常的!
  • @aschepler 你说得对,我在找 +=

标签: c++ operator-overloading friend


【解决方案1】:

这个

template <T, int num1, int num2 > friend  Stack<T, num1>& operator+(Stack<T, num1>& s1, const Stack<T, num2>& s2);

声明一个operator+函数模板,它接受一个T类型的值、一个int类型的值和另一个int类型的值作为模板参数作为你的类模板的朋友。请注意,您声明为朋友的函数模板不是您在Stack 定义之上声明的那个。模板参数列表是不同的。在Stack的定义f之上,声明:

template <class T, int num1, int num2>
//           ^ type parameter
Stack<T, num1>& operator+(Stack<T, num1>& s1, const Stack<T, num2>& s2);

但是在你声明的朋友声明中

template <T, int num1, int num2>
//        ^ non-type parameter
Stack<T, num1>& operator+(Stack<T, num1>& s1, const Stack<T, num2>& s2);

你必须写

template <class U, int num1, int num2> friend Stack<U, num1>& operator+(Stack<U, num1>& s1, const Stack<U, num2>& s2);

让你原来的operator+模板成为类模板Stack的朋友...

除此之外,我建议你停下来考虑一下这样的表达是否真的是个好主意

a + b

隐式修改a。如果您真的必须为此使用运算符,operator+= 可能是表达这些语义的更好方法(就个人而言,我可能只是在这里坚持使用 append 函数)。由于operator+= 必须是非静态成员函数,因此您最初的问题也会消失……

【讨论】:

  • 哦,关于“a”应该保持等于的事实,你是绝对正确的......但是关于模板问题......所以问题是我应该使用 U 而不是 T,因为 T是否已经引用了 Stack 类的模板类?如果我是对的,我可以将 T 留在类上方的声明和类下的实现上,并且仅在友谊中使用 U,还是我必须在任何地方使用相同的字母?
  • @AlbertoSinigaglia 问题是在你的类模板Stack 中,标识符T 表示一个类型。因此,如果你写template &lt;T, ...&gt;,那么第一个参数不是类型,而是T 类型的值,就像template &lt;int, ... 中的第一个参数是int 类型的值,而不是int 类型本身…
  • ...要使模板参数成为类型,您必须编写template &lt;class T, ...template &lt;typename T, ... 但是,由于T已经用作Stack的第一个参数,因此您不能使用它将您朋友的第一个参数命名为[temp.local]/6。因此,您必须选择其他名称。无论如何,这只是一个名字。参数名称不是签名的一部分。 template &lt;class T&gt; void f(); 是与template &lt;class U&gt; void f(); 完全相同的模板...
  • 嗯,谢谢...如果可以的话,我只是另一个问题...为什么我不能在运算符中创建这个变量? Stack&lt;U, num&gt;::Entry * p = element.first;
  • 原来我错过了前面的“typename”,如果我不明白为什么我必须把它放上去
猜你喜欢
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
  • 2020-02-07
  • 2020-10-17
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多