刷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的形式在头文件中定义 二、将类的声明和定义分开放,声明放在头文件,定义放在源文件
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; } #endifSales_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&); #endifSales_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; }