使用Enum类和运算符重载分隔标题

时间:2016-05-18 01:25:21

标签: c++ class enums linker namespaces

我正在完成第36页使用C ++ 2e 编程原则和练习的练习

我有:

  • 班级界面 - > d0.h
  • 课程实施 - > d0.cpp
  • 具有类枚举减速和运算符重载的标题
  • 主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

我的理解是将枚举和(枚举类?)放在自己的标题中是一种好习惯。通过扩展,在那里包含运算符重载似乎是合乎逻辑的。

正确的方法是在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;
}

2 个答案:

答案 0 :(得分:1)

要解决此问题,我将运算符从 Month.h 重载到新文件 Month.cpp

在此之后,我得到了一些非常奇怪的错误,关于编译器无法识别像vector这样的类型。调查进一步显示,../../std_lib_facilities.h包含 d0.h 已包含许多标准库组件,但也有using namespace std

知道这一点后,我用../../std_lib_facilities.h替换std库头的任何实例,然后编译所有内容。

注意:std_lib_facilities.h是本书的标题。它试图将读者与图书馆的一些细节及其包含在一般情况下隔离开来。

答案 1 :(得分:1)

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

  • inline(如果定义位于class正文中,或者如果constexpr具有static),则表示这意味着
  • 全球范围内的
  • namespace
  • 匿名template
  • 一个extern template(有一些涉及rowText = "mary have a little lamb" 的注意事项)