【问题标题】:Porting Windows code to Mac将 Windows 代码移植到 Mac
【发布时间】:2015-08-20 11:48:25
【问题描述】:

我正在将 C++ 代码从 Windows 迁移到 Mac。 我选择使用 C++ 语言的 OS X 命令行工具。

这里是sn-p的代码:

    #ifndef __PRIORITYQUEUE_H__
    #define __PRIORITYQUEUE_H__
    #include <queue>

    template <typename T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type>>
    class PriorityQueue : public std::priority_queue<T, Container, Compare>
    {
    public:
        PriorityQueue() {}
        PriorityQueue(const PriorityQueue& pq) {priority_queue(pq);}   // line:13
        explicit PriorityQueue(const Compare& compare) {priority_queue(compare);}
        PriorityQueue(const Compare& compare, const Container& container) {priority_queue(compare, container);}
        template<class Iter> PriorityQueue(Iter first, Iter last) {priority_queue(first, last);}
        template<class Iter> PriorityQueue(Iter first, Iter last, const Compare& compare) {priority_queue(first, last, compare);}
        template<class Iter> PriorityQueue(Iter first, Iter last, const Compare& compare, const Container& container) {priority_queue(first, last, compare, container);}
    ......
    #endif

还有其他文件会包含这个头文件。 当我编译它时,会发生以下错误:

  1. /Users/yingyhe/Projects/SASCode/SASPRLib/PriorityQueue.h:13:53:未知类型名称'priority_queue';您指的是“PriorityQueue”吗?
  2. /Users/yingyhe/Projects/SASCode/SASPRLib/PriorityQueue.h:13:68:重新定义“pq”

似乎这个头文件被多次包含,但我使用了#ifndef - #define - #endif 来避免这种情况。

然后我把这个头文件放到一个新的项目中,没有其他文件包含它,就可以编译成功了。是有线的,谁能告诉我为什么? 非常感谢!!!

【问题讨论】:

  • 你需要一个头文件来声明一个名为priority_queue的模板。
  • 不要使用带有双下划线或以下划线和大写字母开头的标题保护。它们由实现保留。
  • 我会更加强调前面的评论——你不应该使用任何双下划线的宏名称,无论它们是否用于包含保护。

标签: c++ compiler-errors osx-yosemite


【解决方案1】:

您忘记了 std:: 前缀。

我怀疑您通常在包含此文件之前将其包含在 using namespace std; 的位置。

但是还有更多的问题。

首先,标准库容器并非用作基类。
不要这样做。

基类在 initialiser list 中初始化,而不是在构造函数主体中,例如爪哇:

PriorityQueue(const PriorityQueue& pq) : std::priority_queue(pq) {} 

您收到重新定义错误,因为您声明了一个与参数同名的局部变量。

在函数体中,

std::priority_queue(pq);

等价于

std::priority_queue pq;

这遵循“如果它可以是一个声明,它就是一个声明”的规则。

如果没有其他文件包含头文件,则根本不会编译它,这就是它在这种情况下工作的原因。
它将为包含它的每个源文件编译一次,这与预期的一样 - “包含防护”可防止 翻译单元 中的多个包含,并且每个翻译单元都是单独编译的。

【讨论】:

  • 嗨 molbdnilo,感谢您的回复,我已更改为:PriorityQueue(const PriorityQueue& pq) : std::priority_queue(pq) {} 但出现另一个错误:/Users/yingyhe/ Projects/SASCode/SASPRLib/PriorityQueue.h:13:59:成员初始化程序“priority_queue”未命名非静态数据成员或基类。
【解决方案2】:

我将第 13 行更改为:

`PriorityQueue(const PriorityQueue& pq) : priority_queue<T, Container, Compare>(pq) {}`

编译通过了

【讨论】: