zoukankan      html  css  js  c++  java
  • c/c++ 头文件的血案

    头文件的血案

    不小心在一个头文件里,加了函数的定义,结果导致编译时,提示这个函数被重复定义:(

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

    从上面2次错误的经验,感受到了,c++编译器的脾气了。

    编译阶段:编译器编译到某个函数print_total调用的地方时,就要去前面找这个函数的声明或者定义,如果只有声明没有定义,就先把定义的地方预留出来。

    链接阶段:把在编译阶段预留出函数print_total的定义的空缺,填补上。(print_total的定义在文件Quote.cpp里)

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    个人博客
    个人博客
    5.4
    4.30
    4.29
    4.28
    4.27
    4.26
    4.25
    4.24
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10191612.html
Copyright © 2011-2022 走看看