刷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_INCLUDEclass 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;elses = 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_INCLUDEclass 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;elses = 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_INCLUDEclass 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;elses = 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;
}

error LNK2005 --类的声明和定义放在一个文件中相关推荐

  1. 将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中

    将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中 写这种.h和.cpp文件分开的大程序,虽然对很多人来说很简单,对自己来说算是第一次吧,好好学C++,加油~ 题目:定义Point类,由 ...

  2. 函数声明放在头文件中,函数的定义放在实现文件中,然后在主函数中调用

    1.文件的组织结构如下图: 2.Menu.h内容如下: #ifndef MENU_H #define MENU_H int add(int a,int b); int minus(int a, int ...

  3. C++ : 编译单元、声明和定义、头文件作用、防止头文件在同一个编译单元重复引用、static和不具名空间...

    转 自:http://www.cnblogs.com/rocketfan/archive/2009/10/02/1577361.html 1. 编译单元:一个.cc或.cpp文件作为一个编译单元,生成 ...

  4. 为什么C++模板函数的声明与实现都放在.h文件中

    引用C++primer的话:C++支持两种模板编译模式包含模式(Inclusion   Model )和分离模式(Separation Model) 1. 包含编译模式 在包含编译模式下,在每个模板被 ...

  5. Objective-C 2.0 with Cocoa Foundation --- 3,类的声明和定义

    3,类的声明和定义 本系列讲座有着很强的前后相关性,如果你是第一次阅读本篇文章,为了更好的理解本章内容,笔者建议你最好从本系列讲座的第1章开始阅读,请点击这里 . 上一章 我 们写了一个非常简单的Ob ...

  6. mfcs100ud.lib(dllmodul.obj):error LNK2005: _DllMain@12 已经在 MSVCRTD.lib(dllmain.obj) 中定义

    mfcs100ud.lib(dllmodul.obj):error LNK2005: _DllMain@12 已经在 MSVCRTD.lib(dllmain.obj) 中定义 简单地说,就是产生错误的 ...

  7. 习题 8.5 将本章的例8.4改写为一个多文件的程序:1.将类定义放在头文件arraymax.h中;2.将成员函数定义放在源文件arraymax.cpp中;3.主函数放在源文件file1.cpp中。

    C++程序设计(第三版) 谭浩强 习题8.5 个人设计 习题 8.5 将本章的例8.4改写为一个多文件的程序: 1.将类定义放在头文件arraymax.h中: 2.将成员函数定义放在源文件arraym ...

  8. Python——类的声明与定义

    类的声明与定义 Python 是一门面向对象的语言.面向对象编程 - Object Oriented Programming(简称 OOP)是一种编程思想,在面向对象编程中,把对象作为程序的基本单元, ...

  9. 为什么模板函数的声明和实现都放在.h文件中

    当你不使用这个模板函数或模板类,编译器并不实例化它,当你使用时,编译器需要实例化它,因为编译器是一次只能处理一个编译单元,也就是一次处理一个cpp文件,所以实例化时需要看到该模板的完整定义.所以都放在 ...

最新文章

  1. 负数运算_小学生必备科学常识100问-34数学史(7):负数的产生
  2. Android输入法遮挡了输入框,使用android:fitsSystemWindows=“true“后界面顶部出现白条解决方案
  3. linux shell 实现自增版本号
  4. beego 注解路由无效问题分析
  5. 【数字信号处理】相关函数 ( 能量信号 | 能量信号的互相关函数 | 能量信号的自相关函数 )
  6. Commons Logging 快速入门(五)
  7. 树莓派应用实例5:测量土壤湿度
  8. Quartz-异常处理
  9. 关于库存 库存BAPI
  10. 7月清北学堂培训 Day 5
  11. 服务器任务管理器详细信息,任务管理器服务器主机
  12. centos6安装mysql并远程连接_阿里云服务器上安装redis并实现远程连接
  13. 用户名 不在 sudoers文件中,此事将被报告。
  14. 做游戏,学编程(C语言) 10 僵尸危机
  15. 微信小程序 audio 音频 组件
  16. speedoffice表格如何快速复制整张工作表
  17. 四、LockSupport与线程中断
  18. ac9260网卡linux,160Mhz频宽的怒吼,Intel Wireless-AC 9260 无线网卡评测
  19. 学微积,用手机,人人“知识共享”学真知
  20. 修正 Newton 公式

热门文章

  1. 怎么自定义服务器的404,给网站设置404页面详细图文方法
  2. Fuzer:华坤道威自研百万级任务调度系统
  3. Java市场饱和?谁在忽悠你?
  4. 使用JSP内置对象编写登录验证页面
  5. Oracle、MySQL等主流数据库部分语法区别
  6. 【调剂】国家蛋白质科学中心·北京贺福初院士课题组招收硕士研究生
  7. 【NLP】6 gensim word2vec基于中文语料库实战——中文wiki百科、清华大学自然语言处理实验室数据集、搜狗全网新闻数据集
  8. Oracle 误删表后数据恢复操作
  9. OpenLayers入门(二)
  10. [Linux发行版] 常见Linux系统下载