我正在第338页完成使用C++ 2e进行编程原理和实践的练习

我有:

  • A类接口(interface)-> d0.h
  • 一个类实现-> d0.cpp
  • 具有类枚举减速度和运算符重载的 header
  • 主cpp文件-> d0m.cpp

  • 尝试编译时收到以下错误:
    g++ d0.cpp d0m.cpp -o d0.o -std=gnu++11
    /tmp/name/cc09EWiA.o: In function `chrono::operator<<(std::ostream&, chrono::Month const&)':
    d0m.cpp:(.text+0x0): multiple definition of `chrono::operator<<(std::ostream&, chrono::Month const&)'
    /tmp/name/ccPAVaW9.o:d0.cpp:(.text+0x0): first defined here
    collect2: error: ld returned 1 exit status
    

    看来问题是Month.h中的运算符重载

    这就是我理解要包含的内容的方式:
    month.h
    ^
    |
    |
    d0.h<---------d0m.cpp
    ^
    |
    |
    d0.cpp
    

    据我了解,将枚举和(枚举类?)放在自己的 header 中是一种好习惯。通过扩展,似乎也可以在其中包含操作符重载。

    是这样做的正确方法,是在Month.h中定义运算符重载并在Month.cpp中创建定义吗?
    // Month.h -> Enum Class used in Date71 class definition in d0.h
    #pragma once
    #include <string>
    #include <iostream>
    #include <vector>
    
    namespace chrono
    {
        enum class Month
        {
            jan=1,feb,mar,apr,jun,jul,aug,sep,oct,nov,dec
        };
    
        const vector<string> month_tbl = {"January",
                        "February",
                        "March",
                        "April",
                        "May",
                        "June",
                        "July",
                        "August",
                        "September",
                        "November",
                        "December"};
    
        extern ostream& operator<<(ostream& os, const Month& m)
        {
            return os << month_tbl[int(m)];
        }
    }
    
    #pragma once
    #include "../../std_lib_facilities.h"
    #include "Month.h"
    
    namespace chrono
    {
        class Date71
        {
            public:
                Date71(int y, Month m, int d); // check for valid date and initialize
                void add_date(int n); // increase Date by n days
                Month month();
                int day();
                int year();
            private:
                int y; // year
                Month m;
                int d; // day
        };
    
    
    
    // d0.cpp
    #include "../../std_lib_facilities.h"
    #include "d0.h"
    
    namespace chrono
    {
        Month Date71::month(){return m;}
        int Date71::day(){return d;}
        int Date71::year(){return y;}
    
        void Date71::add_date(int n)
        {
            d = (d < 31) ? d+n : d;
        }
    
        ostream& operator<<(ostream& os, Date71& b)
        {
            return os <<'('<<b.year()
                  <<','<<b.month()
                  <<','<<b.day()<<')';
        }
    }
    
    //d0m.cpp
    #include "../../std_lib_facilities.h"
    #include "d0.h"
    using namespace std;
    
    int main(void)
    {
        chrono::Date71 forth(1978,chrono::Month::jul,25);
        chrono::Date71 forthC = forth;
        thirdC.add_date(1);
        chrono::Date71 forthW(1978,chrono::Month::jul,35);
    
        cout << forth;
        cout << forthC;
    
        return 0;
    }
    

    最佳答案

    多个翻译单元中可能出现的每个函数定义必须至少为以下之一:

  • inline(如果定义在class主体中或如果它具有constexpr,则暗含该字符)
  • 全局范围内的static
  • 匿名namespace中的
  • 一个template(带有一些涉及extern template的警告)
  • 10-04 16:31
    查看更多