【问题标题】:Syntax for C++ operator overloading in a class类中 C++ 运算符重载的语法
【发布时间】:2020-10-18 13:07:08
【问题描述】:

背景

我在 this course 自学 C++。我正在尝试使用友元函数(Assignment 4.2 重载类中的运算符。

编辑

链接的问题没有回答我的问题。该问题的公认解决方案提供了一种在 header + cpp 文件中实现模板的方法(并非全部在同一个文件中)。

事实上,我已经参考了这个问题来部分了解我的情况。

我的尝试

使用Approach 2,我几乎让我的代码工作了(请参阅神秘的错误消息)。原来我错过了<>。 (Solution manual)。

我试过谷歌搜索,但没有其他人遇到过这种情况

  1. 好友功能,
  2. 运算符重载,以及
  3. 在模板类中

同时。

我的理由

你不应该使用类公共函数来做运算符重载,因为调用函数的对象会被隐式传递,占用一个函数参数。让重载的运算符对称(无论是在使用上还是在定义上)都是更好的代码风格。

friend 的用法由讲义建议。

问题

  1. 为什么需要<>
  2. 有没有更好的方法在模板类中进行运算符重载?
  3. (可选)如何理解错误消息?

谢谢。

代码

stack.h

#include <iostream>
#include <vector>
using std::cout;
using std::vector;

template <typename T>
class Stack;

template <typename T>
Stack<T> operator+(Stack<T> a, Stack<T> b);

template <typename T>
class Stack { // use default constructors and destructors
private:
    vector<T> s;
public:
    bool empty();
    void push(const T &item);
    T& top();
    void pop();
    friend Stack<T> operator+(Stack<T> a, Stack<T> b); // need operator+<>
};

stack.cpp

#include <iostream>
#include <vector>
using std::cout;
#include "stack.h"

template <typename T>
bool Stack<T>::empty() {
    return s.empty();
}

template <typename T>
void Stack<T>::push(const T &item) {
    s.push_back(item);
}

template <typename T>
T& Stack<T>::top() {
    return s.back();
}

template <typename T>
void Stack<T>::pop() {
    s.pop_back();
}

template <typename T>
Stack<T> operator+(Stack<T> a, Stack<T> b) {
    Stack<T> temp;
    while (!b.empty()) {
        temp.push(b.top()); 
        b.pop();
    }
    while (!a.empty()) {
        temp.push(a.top());
        a.pop();
    }
    Stack<T> c;
    while (!temp.empty()) {
        c.push(temp.top());
        temp.pop();
    }
    return c;
}

int main() {
    Stack<int> a, b;
    a.push(1);
    a.push(2);
    b.push(3);
    b.push(4);
    Stack<int> c = a + b;
    cout << c.top() << "\n";

    return 0;
}

错误信息

Undefined symbols for architecture x86_64:
  "operator+(Stack<int>, Stack<int>)", referenced from:
      _main in stack-d2f02a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1

【问题讨论】:

  • 感谢您重新打开。一般来说,对于有权单枪匹马关闭的人来说,给提问者一些时间来解释他们的情况可能会很好。
  • “我试过谷歌搜索,但没有其他人遇到过” - 这个人似乎有stackoverflow.com/questions/3989678/…
  • 而且由于操作符实际上只是具有时髦名称的函数,所以这个人似乎在问你做的同样的事情,没有操作符细节stackoverflow.com/questions/6803099/…
  • @StoryTeller-UnslanderMonica 感谢您为我指明了正确的方向。下一次,我会在点击“提问”之前尝试最后一次 google-search,因为一旦我有一个更清晰、格式正确的问题,google 就会变得更容易。

标签: c++ templates polymorphism operator-overloading friend


【解决方案1】:

您需要添加&lt;&gt;(或&lt;T&gt;)以使朋友声明引用声明的运算符模板。没有那个朋友声明将声明一个未定义的非模板operator+,这就是你得到链接器错误的原因。

顺便说一句:您也可以像这样显式指定模板参数

// refers to the instantiation of template operator+ for T 
friend Stack<T> operator+<T>(Stack<T> a, Stack<T> b);
//                       ^^^

使用&lt;&gt;时,模板参数T会从函数参数中推导出来,效果相同。

// refers to the instantiation of template operator+ for T 
// T is deduced from function parameters
friend Stack<T> operator+<>(Stack<T> a, Stack<T> b);
//                       ^^

【讨论】:

  • 好的! &lt;&gt; 是隐含的&lt;T&gt;,需要引用模板。奇怪的是,如果我还将&lt;T&gt; 放入.cpp 文件中,我会得到function template partial specialization is not allowed。这令人困惑。所以我需要头文件中的&lt;T&gt;,而不需要.cpp 文件中的&lt;T&gt;。这是为什么呢?
  • @BenjaminWang 在好友声明中,添加&lt;T&gt; 表示为T 特化,即operator+&lt;T&gt; 好友。在.cpp 文件中你定义了模板,那么你不应该添加它,就像其他函数模板定义一样。
猜你喜欢
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多