簡體   English   中英

鏈接器未能找到重載運算符

[英]Linker failing to find overloaded operator

我正在嘗試為我的一個類重載<<運算符,但鏈接器始終無法找到重載。 一直在網上搜索我錯過的關於如何聲明和實現運算符重載的任何內容,但對我來說似乎沒有什么特別之處。 有什么想法可以解決這個問題嗎?

Undefined symbols for architecture x86_64:
  "memath::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, memath::Vector3 const&)", referenced from:
      _main in mecli.cxx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

向量3.h

#include <string>
#include <iostream>

namespace memath {

class Vector3 {

public:
    double x;
    double y;
    double z;

    Vector3();

    std::string to_string() const;

    friend std::ostream& operator<<(std::ostream &strm, const Vector3 &a);

};

};

向量3.cxx

#include <string>
#include <iostream>
#include <sstream>

#include "vector3.h"

using namespace memath;

Vector3::Vector3() : Vector3(0, 0, 0) {}

std::string Vector3::to_string() const {
    std::ostringstream r;
    r << "Vector3" << "(" << this->x << "," << this->y << "," << this->z << ")";
    return r.str();
}

std::ostream& operator<<(std::ostream &strm, const Vector3 &a) {
    strm << a.to_string();
    return strm;
}

mecli.cxx

#include <iostream>
#include <cstdlib>
#include <string>

#include "vector3.h"

int main(int argc, char** argv) {
    memath::Vector3 vec1;
    std::cout << vec1 << std::endl;
}

因為Vector3在命名空間memath ,友元聲明聲明了memath::operator<< ,但您隨后定義了::operator<< 所以只需使定義與聲明匹配:

std::ostream& memath::operator<<(std::ostream &strm, const Vector3 &a) {
//            ^~~~~~~~

跟進問題,為什么不using namespace memath; 在這種情況下,似乎在文件頂部很重要,並特別排除此運算符重載?

這對這個運營商來說並不特別。 其實並不是特別針對運營商。 你會得到與函數相同的行為。 並且它並不特別適用於朋友聲明。

所以讓我們在一個更簡單的例子中看到這一點:

namespace ns
{
    struct X
    {
        int foo(int);  // => ::ns::X::foo
    };

    int bar(int);      // => ::ns::bar
}

using namespace ns;

int X::foo(int a) { return a + 1; } // (1)  => ::ns::X::foo
int bar(int a) { return a * 2; }    // (2)  => ::bar

就像在您的示例中一樣, foo按您的預期工作,但bar是不明確的,就像您的operator<< 那么兩者有什么區別呢? 這是一個簡單的解釋:

(1):這是限定名foo的定義。 X::是使它合格的原因。 所以在X搜索foo 但什么是X X是不合格的名稱 ID。 所以現在對X執行不合格的查找。 這意味着在當前命名空間(全局)和using指令引入的所有命名空間中搜索X 在這種情況下, X只能在命名空間ns找到。 所以X::foo被解析為ns::X::foo這使得它成為類ns::X的方法foo的聲明。

(2) 這是不合格名稱bar的定義。 由於bar是非限定的,這被解釋為當前命名空間(全局命名空間)中名稱bar的聲明。 因為bar是一個被聲明的新名稱,所以不執行查找。 所以bar::bar的聲明。

請記住,這是一個簡化的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM