【问题标题】:Conflict between Using Declaration and Forward Declaration使用声明和转发声明之间的冲突
【发布时间】:2013-02-28 18:46:08
【问题描述】:

我们和斗牛犬一起去散步吧:)

假设我有一个命名空间 Street::House(在命名空间 Street 内),其中类 Bulldog声明(让它在 House/Bulldog.hpp 中):

namespace Street {
namespace House {
class Bulldog {};
}
}

然后,我有Bulldog.hpp

#include "House/Bulldog.hpp"    

namespace Street {
using House::Bulldog;
}

注意发生了什么:我将Street::House::Bulldog 的声明注入 到命名空间Street 作为Street::Bulldogusing 声明。

然后,我有 Owner.hppBulldog转发声明

namespace Street {
class Bulldog;

class Owner {
  Bulldog* bulldog;
};
}

最后,我有Owner.cpp

#include "Owner.hpp"
#include "Bulldog.hpp"

namespace Street {
// Implementation of Owner...
}

Owner.cpp出现编译错误:

error: 'Bulldog' is already declared in this scope

这种现象的自然解释似乎是 C++ 将这 2 个Bulldog 类视为不同,但为什么呢?在这种情况下,我看不出有任何歧义,也就是说,如果编译器正确实现它,它实际上可以工作。

您可以建议哪些解决方法?我能想到的一种方法是简单地从Owner.hpp 中删除Bulldog前向声明,并将#include "Bulldog.hpp"Owner.cpp 移动到Owner.hpp。但是,这将导致完全包含而不是前向声明

【问题讨论】:

  • Clang 有一个更具描述性的消息error: target of using declaration conflicts with declaration already in scope
  • 这不是编译器错误,注入的声明不能这样工作。

标签: c++ compiler-errors include forward-declaration using-declaration


【解决方案1】:

看来您可以通过将Bulldog.hpp 更改为说来解决此问题

namespace Street {
    namespace House {
        class Bulldog;
    }
    using House::Bulldog;

    // ...
}

这在 Clang 中对我有用。

【讨论】:

  • 不幸的是,现在错误只是移动到示例的第 5 行,但这是意料之中的,因为实际上没有任何改变。
  • @Haroogan:真的吗?它使用 Clang 对我来说编译得很好。
  • @Haroogan 可以正常工作ideone.com/hGNbp1(是的,有些地方发生了变化,using House::Bulldog 不等同于在Street 中声明Bulldog
  • @Haroogan,您的原始名称因(this) 不起作用的相同原因而不起作用,为类型创建新名称不会更改原始名称;如果 class Bulldog 实际上不是一个类,而是 using-injected 或 typedef-ed 类型名称,则不能转发声明。这是两个不同的命名空间(标签名称和类型);与 C 不同,C++ 只是允许您自动将标记名称用作类型,但它们仍然是不同的。
  • @Haroogan:由于链接的工作方式,我认为不可能提出任何技术来完全消除通过检查标头来判断Bulldog 来自哪个命名空间的能力。
【解决方案2】:

Owner.hpp 你写的:

namespace Street {
class Bulldog;

class Owner {
  Bulldog* bulldog;
};
}

应该是

namespace Street {
namespace House {
class Bulldog;
}

class Owner {
  House::Bulldog* bulldog;
};
}

您不小心转发声明了Street::Bulldog,它不是一个真正的类,而不是Street::House::Bulldog,它一个真正的类。因此,您在 Owner.cpp 中的实现令人不安,因为 Bulldog* 是模棱两可的。它不知道您是指声明的类 Street::Bulldog 还是声明的(也已定义,尽管编译器不关心这一点Street::House::Bulldog

由于您要转发声明的类是 Street::House::Bulldog,因此您需要在 .hpp 文件的声明中包含第二个命名空间 House

【讨论】:

    猜你喜欢
    • 2021-08-11
    • 2018-11-23
    • 1970-01-01
    • 2017-11-09
    • 2019-05-16
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多