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

  • 相关阅读:
    斐波那契数列 的两种实现方式(Java)
    单链表反转
    单链表合并
    两个有序list合并
    list去重 转载
    RemoveAll 要重写equals方法
    Java for LeetCode 138 Copy List with Random Pointer
    Java for LeetCode 137 Single Number II
    Java for LeetCode 136 Single Number
    Java for LeetCode 135 Candy
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10191612.html
Copyright © 2011-2022 走看看