刷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 &)" (??YSales_data@@QAEAAV0@ABV0@@Z) 已经在 main.obj 中定义
1>Sales_data.obj : error LNK2005: "class Sales_data __cdecl operator+(class Sales_data const &,class Sales_data const &)" (??H@YA?AVSales_data@@ABV0@0@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;
}