【问题标题】:Why do I need to use the empty namespace to get this to compile? [duplicate]为什么我需要使用空命名空间来编译它? [复制]
【发布时间】:2020-03-12 06:16:45
【问题描述】:

***JVApen 针对这种特殊情况提供的解决方案。我不得不在 item.h 文件中内联运算符重载,因为我没有使用实现文件。

我创建了一个包含 2 个头文件的项目。一个用于项目结构,另一个用于使用该结构的列表。我收到以下错误,我知道如果我将结构标头包装在无名命名空间中,它们会消失,但根本原因是什么,将来如何避免?

1>Project2.obj : error LNK2005: "class std::basic_istream > & __cdecl operator>>(class std::basic_istream > &,struct item &)" (??5@YAAAV?$basic_istream@DU? $char_traits@D@std@@@std@@AAV01@AAUitem@@@Z) 已在linkedList.obj中定义 1>Project2.obj : 错误 LNK2005: "class std::basic_ostream > & __cdecl operator &,struct item const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits @D@std@@@std@@AAV01@ABUitem@@@Z) 已经在linkedList.obj中定义了

我没有为结构创建一个实现文件,所有的东西都是原型并在头文件中定义的,这是什么原因造成的?

我已将 item.h 包含在我的 linkedList.h 中,如下所示:

item.h

#pragma once

#include <iostream>
#include <iomanip>
#include <string>


struct item {
    std::string name;
    double price;
    int currentInv;
    int minInv;

    item(std::string name = "default", double price = 0,
        int currentInv = 0, int minInv = 0)
        : name(name), price(price), currentInv(currentInv), minInv(minInv)
    {}

    bool operator<(const item& rhs) {
        return (this->name < rhs.name);
    }

    bool operator>(const item& rhs) {
        return (this->name > rhs.name);
    }

    bool operator==(const item& rhs) {
        return (this->name == rhs.name);
    }

    bool operator<=(const item& rhs) {
        return ((this->name < rhs.name) || (this->name == rhs.name));
    }

    bool operator>=(const item& rhs) {
        return ((this->name > rhs.name) || (this->name == rhs.name));
    }
};

std::ostream& operator<<(std::ostream& out, const item& printMe) {
    out << std::fixed << std::setprecision(2);
    return (out << std::setw(31) << std::left << printMe.name << ' ' <<
        std::right << std::setw(6) << printMe.price << ' ' << std::setw(3) <<
        printMe.currentInv << ' ' << std::setw(3) << printMe.minInv);
}

std::istream& operator>>(std::istream& in, item& fillMe) {
    return (in >> fillMe.name >> fillMe.price >> fillMe.currentInv >>
        fillMe.minInv);
}

linkedList.h

#pragma once

#include "item.h"

class List {
private:
//--- Node Class
class node {
public:

//--- Node Variables

    item data{};                            // item struct
    node* next;                             // ptr to next node

//--- Node Constructors

    node()
        : next(NULL) {}
    node(item& data, node* ptr = NULL)
        : data(data), next(ptr) {};

};

//--- Class Variables
int mySize;                                 // list Size
node* first;                                // first node

public:

//--- List Constructors
List();                                     
List(List& original);                       // copy constructor

//--- List Destructor
~List();                                    // destructor

//--- List Overrides
List& operator=(const List rhs);            // = overload

//--- List Public Functions
bool empty();                               

int nodeCount();                            
int search(const std::string findMe);       // find a piece of data

void addItem(item& addme);                  // add node
void changeItem();                          // change an item
void display(std::ostream& out);            // print out
void displayReversed(std::ostream& out);    // reverse print
void remove(int index);                     // remove node at index
void fileOut(std::ostream out);             // end of program file

private:

//---List Private Functions
void addItemPrivate(item& addme, node* ptr);
};

std::ostream& operator<<(std::ostream& out, const List& outMe);

【问题讨论】:

  • 您使用的是哪个编译器? #pragma once 可能不受支持
  • 免费功能应该我标记为内联,否则你违反了ODR
  • 内联解决了这个问题。我无法将其标记为已解决,但谢谢 JVApen。

标签: c++


【解决方案1】:

在 C++ 编程语言中,#pragma once 是非标准的。在您的头文件中使用替代方法 ifndef,如下所示

item.h/////////////

#ifndef ITEM_H
#define ITEM_H
... contents of item.h
#endif /* !ITEM_H */


linkedList.h ////////////

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
... contents of linkedList.h
#endif /* !LINKEDLIST_H */

注意:您必须至少有一个包含linkedlist.h 文件的cpp 文件。您不需要将实现移动到 cpp 文件。只需创建一个linkedlist.cpp 文件并在其中包含linkedlist.h 文件。

【讨论】:

  • 虽然 #pragma once 没有标准化,但大多数现代编译器都支持它,并且不是 OP 问题的原因
【解决方案2】:

#pragma once 防止包含文件被同一个 .cpp 文件多次包含。

但是,它不会阻止它再次包含在另一个 .cpp 文件中。因此,项目中包含 item.h 的每个 .cpp 文件都将创建这两种方法的实现。

大多数链接器足够聪明,可以忽略类方法的那些重复项,但是您的 > 运算符不是类的一部分。我知道的唯一解决方案是将它们放入 .cpp 文件中。

【讨论】:

  • 超过Most linkers are smart enough to ignore those duplicates for class methods 标准说类中定义的方法自动标记为内联
猜你喜欢
  • 2015-02-10
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多