Using声明和Forward声明的冲突

Conflict between Using Declaration and Forward Declaration

本文关键字:声明 冲突 Using Forward      更新时间:2023-10-16

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

说我有一个命名空间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.hpp,其中Bulldog类是前向声明的:
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++将这两个Bulldog类视为不同的,但是为什么呢?在这种情况下,我看不到任何歧义,也就是说,如果编译器正确实现,它实际上可以工作。

你有什么建议吗?我能想到的一种方法是简单地从Owner.hpp中删除Bulldog前向声明,并将#include "Bulldog.hpp"Owner.cpp移动到Owner.hpp。但是,这将导致精确包含而不是前向声明

似乎你可以通过改变Bulldog.hpp

来解决这个问题
namespace Street {
    namespace House {
        class Bulldog;
    }
    using House::Bulldog;
    // ...
}

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名称空间。