c/c++ 头文件的血案
程序员文章站
2022-03-24 22:42:11
头文件的血案 不小心在一个头文件里,加了函数的定义,结果导致编译时,提示这个函数被重复定义:( Quote.h mainQuote.cpp 编译方法: 编译结果: shell multiple definition of c++ ifndef __QUOTE_H__ define __QUOTE_H ......
头文件的血案
不小心在一个头文件里,加了函数的定义,结果导致编译时,提示这个函数被重复定义:(
quote.h
#ifndef __quote_h__ #define __quote_h__ #include <iostream> class quote{ public: quote() = default; quote(const std::string& book, double pri) :bookno(book), price(pri){} std::string isbn() const{return bookno;} virtual double net_price(std::size_t n)const{ return n * price; } virtual ~quote() = default; private: std::string bookno; protected: double price = 0.0; }; class bulk_quote : public quote{ public: bulk_quote() = default; bulk_quote(const std::string&, double, std::size_t, double); double net_price(std::size_t n)const override; private: std::size_t min_qty = 0;//适用于折扣的最低购买数量 double discount = 0.0;//折扣额 }; //不小心在这个头文件里,加了下面这个函数的定义,结果导致编译时,提示这个函数被重复定义:( double print_total(std::ostream& os, const quote& item, size_t n){ double ret = item.net_price(n); os << "isbn: " << item.isbn() << " # sold: " << n << " total due: " << ret << std::endl; return ret; #endif
quote.cpp
#include "quote.h" bulk_quote::bulk_quote(const std::string& book, double p, std::size_t qty, double disc): quote(book, p), min_qty(qty), discount(disc){} double bulk_quote::net_price(std::size_t cnt)const { if(cnt >= min_qty){ return cnt * (1 - discount) * price; } else{ return cnt * price; } }
mainquote.cpp
#include "quote.h" int main(){ quote q("01",100.5); double d = print_total(std::cout, q, 1); bulk_quote bq("01", 100.5, 5, 1); }
编译方法:
g++ -g quote.cpp mainquote.cpp -std=c++11
编译结果:
multiple definition of `print_total(std::ostream&, quote const&, unsigned long)`
错误原因,大概知道了,但是不知道为什么
- 因为在quote.cpp里包含了quote.h,在mainquote.cpp里也包含了quote.h,自己错的的认为:在头文件的开头只要加了保护 #ifndef __quote_h__,就不会把quote.h包含2次,导致函数重复定义。但是没有什么卵用,这是为什么呢??? 用g++ -e quote.cpp mainquote.cpp > main.i,生成了预编译后的文件main.i,这个文件里确实有2个地方有print_total的定义。
- 网上说,最好不要在头文件里定义函数和变量,否则会导致重复定义,看来网上说的还真对!但是如果把函数print_total定义为inline函数的话,编译就没有问题。这又是为什么呢???
修改方案1,把函数放到quote.cpp里
quote.h
#ifndef __quote_h__ #define __quote_h__ #include <iostream> class quote{ public: quote() = default; quote(const std::string& book, double pri) :bookno(book), price(pri){} std::string isbn() const{return bookno;} virtual double net_price(std::size_t n)const{ return n * price; } virtual ~quote() = default; private: std::string bookno; protected: double price = 0.0; }; class bulk_quote : public quote{ public: bulk_quote() = default; bulk_quote(const std::string&, double, std::size_t, double); double net_price(std::size_t n)const override; private: std::size_t min_qty = 0;//适用于折扣的最低购买数量 double discount = 0.0;//折扣额 }; #endif
quote.cpp
#include "quote.h" bulk_quote::bulk_quote(const std::string& book, double p, std::size_t qty, double disc): quote(book, p), min_qty(qty), discount(disc){} double bulk_quote::net_price(std::size_t cnt)const { if(cnt >= min_qty){ return cnt * (1 - discount) * price; } else{ return cnt * price; } } double print_total(std::ostream& os, const quote& item, size_t n){ double ret = item.net_price(n); os << "isbn: " << item.isbn() << " # sold: " << n << " total due: " << ret << std::endl; return ret; }
mainquote.cpp
#include "quote.h" int main(){ quote q("01",100.5); double d = print_total(std::cout, q, 1); bulk_quote bq("01", 100.5, 5, 1); }
编译结果:
error: ‘print_total’ was not declared in this scope
错误原因,quote.h里没有函数print_total的声明和定义,所以当然出这个错误
修改方法:加一个函数print_total的声明,就好了。
mainquote.cpp
#include "quote.h" double print_total(std::ostream& os, const quote& item, size_t n); int main(){ quote q("01",100.5); double d = print_total(std::cout, q, 1); bulk_quote bq("01", 100.5, 5, 1); }