1. 程式人生 > >error LNK2005 --類的宣告和定義放在一個檔案中

error LNK2005 --類的宣告和定義放在一個檔案中

刷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;
}