error LNK2005 --類的宣告和定義放在一個檔案中
阿新 • • 發佈:2018-11-05
刷C++primer的時候,將類的宣告和定義均放在標頭檔案中,報錯error LNK2005
1> Sales_data.h
1>Sales_data.obj : error LNK2005: "public: class Sales_data & __thiscall Sales_data::operator+=(class Sales_data const &)" ([email protected]@[email protected]@@Z) 已經在 main.obj 中定義
1>Sales_data.obj : error LNK2005: "class Sales_data __cdecl operator+(class Sales_data const &,class Sales_data const &)" ( [email protected][email protected]@[email protected]@Z) 已經在 main.obj 中定義
1>Debug\Sales_data.obj : warning LNK4042: 物件被多次指定;已忽略多餘的指定
1>E:\C++Projects\PrimerCode\02\Debug\02.exe : fatal error LNK1169: 找到一個或多個多重定義的符號
1>
1>生成失敗。
1>
原始程式碼:
Sales_data.h:
#include <iostream> #include <string> using namespace std; #ifndef SALES_DATA_H_INCLUDE #define SALES_DATA_H_INCLUDE class Sales_data{ //友元函式 friend std::istream& operator >> (std::istream&,Sales_data&); friend std::ostream& operator << (std::ostream&,const Sales_data&); friend bool operator > (const Sales_data&,const Sales_data&); friend bool operator < (const Sales_data&,const Sales_data&); friend bool operator == (const Sales_data&,const Sales_data&); //建構函式 public: Sales_data() {}; Sales_data(const std::string &book):bookNo(book){}; Sales_data(std::istream &is){ is>>*this;}; public: Sales_data& operator += (const Sales_data&); std::string isbn() const {return bookNo;}; private: std::string bookNo; int units_sold; double sellingprice; double saleprice; double discount; }; //Sales_data operator + (const Sales_data&,const Sales_data&); inline std::istream& operator >> (std::istream& in ,Sales_data& s) { in >> s.bookNo >> s.units_sold >> s.saleprice >> s.sellingprice; if(s.sellingprice != 0) s.discount = s.saleprice/s.sellingprice; else s = Sales_data();//輸入錯誤,重置輸入資料 return in; } inline std::ostream& operator << (std::ostream& out ,const Sales_data& s) { out<<s.isbn() << " " << s.units_sold <<" " << s.saleprice <<" " << s.sellingprice ; return out; } inline bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs) { return lhs.isbn()==rhs.isbn(); } inline bool operator == (const Sales_data &lhs,const Sales_data& rhs) { return lhs.bookNo == rhs.bookNo && lhs.units_sold == rhs.units_sold && lhs.sellingprice == rhs.sellingprice && lhs.saleprice == rhs.saleprice; } inline bool operator != (const Sales_data &lhs,const Sales_data & rhs) { return !(lhs==rhs); } Sales_data& Sales_data::operator += (const Sales_data& rhs) { units_sold += rhs.units_sold; saleprice = (rhs.units_sold*rhs.saleprice+units_sold*saleprice)/(rhs.units_sold+units_sold); if(sellingprice!=0) discount = saleprice / sellingprice; return *this; } Sales_data operator + (const Sales_data &lhs,const Sales_data &rhs) { Sales_data ret(lhs);//把lhs的內容拷貝到臨時變數ret中,這種做法便於運算 ret+=rhs; return ret; } #endif
解決辦法:
一、將這兩個函式使用inline的形式在標頭檔案中定義
二、將類的宣告和定義分開放,宣告放在標頭檔案,定義放在原始檔
一、將這兩個函式使用inline的形式在標頭檔案中定義
Sales_data.h
#include <iostream> #include <string> using namespace std; #ifndef SALES_DATA_H_INCLUDE #define SALES_DATA_H_INCLUDE class Sales_data{ //友元函式 friend std::istream& operator >> (std::istream&,Sales_data&); friend std::ostream& operator << (std::ostream&,const Sales_data&); friend bool operator > (const Sales_data&,const Sales_data&); friend bool operator < (const Sales_data&,const Sales_data&); friend bool operator == (const Sales_data&,const Sales_data&); //建構函式 public: Sales_data() {}; Sales_data(const std::string &book):bookNo(book){}; Sales_data(std::istream &is){ is>>*this;}; public: Sales_data& operator += (const Sales_data&); std::string isbn() const {return bookNo;}; private: std::string bookNo; int units_sold; double sellingprice; double saleprice; double discount; }; //Sales_data operator + (const Sales_data&,const Sales_data&); inline std::istream& operator >> (std::istream& in ,Sales_data& s) { in >> s.bookNo >> s.units_sold >> s.saleprice >> s.sellingprice; if(s.sellingprice != 0) s.discount = s.saleprice/s.sellingprice; else s = Sales_data();//輸入錯誤,重置輸入資料 return in; } inline std::ostream& operator << (std::ostream& out ,const Sales_data& s) { out<<s.isbn() << " " << s.units_sold <<" " << s.saleprice <<" " << s.sellingprice ; return out; } inline bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs) { return lhs.isbn()==rhs.isbn(); } inline bool operator == (const Sales_data &lhs,const Sales_data& rhs) { return lhs.bookNo == rhs.bookNo && lhs.units_sold == rhs.units_sold && lhs.sellingprice == rhs.sellingprice && lhs.saleprice == rhs.saleprice; } inline bool operator != (const Sales_data &lhs,const Sales_data & rhs) { return !(lhs==rhs); } inline Sales_data& Sales_data::operator += (const Sales_data& rhs) { units_sold += rhs.units_sold; saleprice = (rhs.units_sold*rhs.saleprice+units_sold*saleprice)/(rhs.units_sold+units_sold); if(sellingprice!=0) discount = saleprice / sellingprice; return *this; } inline Sales_data operator + (const Sales_data &lhs,const Sales_data &rhs) { Sales_data ret(lhs);//把lhs的內容拷貝到臨時變數ret中,這種做法便於運算 ret+=rhs; return ret; } #endif
二、將類的宣告和定義分開放,宣告放在標頭檔案,定義放在原始檔
Sales_data.h
#include <iostream>
#include <string>
using namespace std;
#ifndef SALES_DATA_H_INCLUDE
#define SALES_DATA_H_INCLUDE
class Sales_data{
//友元函式
friend std::istream& operator >> (std::istream&,Sales_data&);
friend std::ostream& operator << (std::ostream&,const Sales_data&);
friend bool operator > (const Sales_data&,const Sales_data&);
friend bool operator < (const Sales_data&,const Sales_data&);
friend bool operator == (const Sales_data&,const Sales_data&);
//建構函式
public:
Sales_data() {};
Sales_data(const std::string &book):bookNo(book){};
Sales_data(std::istream &is){ is>>*this;};
public:
Sales_data& operator += (const Sales_data&);
std::string isbn() const {return bookNo;};
private:
std::string bookNo;
int units_sold;
double sellingprice;
double saleprice;
double discount;
};
Sales_data operator + (const Sales_data&,const Sales_data&);
#endif
Sales_data.cpp
#include "Sales_data.h"
inline std::istream& operator >> (std::istream& in ,Sales_data& s)
{
in >> s.bookNo >> s.units_sold >> s.saleprice >> s.sellingprice;
if(s.sellingprice != 0)
s.discount = s.saleprice/s.sellingprice;
else
s = Sales_data();//輸入錯誤,重置輸入資料
return in;
}
inline std::ostream& operator << (std::ostream& out ,const Sales_data& s)
{
out<<s.isbn() << " " << s.units_sold <<" " << s.saleprice <<" " << s.sellingprice ;
return out;
}
inline bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{
return lhs.isbn()==rhs.isbn();
}
inline bool operator == (const Sales_data &lhs,const Sales_data& rhs)
{
return lhs.bookNo == rhs.bookNo &&
lhs.units_sold == rhs.units_sold &&
lhs.sellingprice == rhs.sellingprice &&
lhs.saleprice == rhs.saleprice;
}
inline bool operator != (const Sales_data &lhs,const Sales_data & rhs)
{
return !(lhs==rhs);
}
Sales_data& Sales_data::operator += (const Sales_data& rhs)
{
units_sold += rhs.units_sold;
saleprice = (rhs.units_sold*rhs.saleprice+units_sold*saleprice)/(rhs.units_sold+units_sold);
if(sellingprice!=0)
discount = saleprice / sellingprice;
return *this;
}
Sales_data operator + (const Sales_data &lhs,const Sales_data &rhs)
{
Sales_data ret(lhs);//把lhs的內容拷貝到臨時變數ret中,這種做法便於運算
ret+=rhs;
return ret;
}