具有相同名称/命名空间但具有不同成员的结构

cpl*_*rat 1 c++ struct c++11

我看到一些奇怪的行为,我在这个结构内联初始化的后期向量中描述.支撑-初始化列表

我希望消除一个未定义行为的可能来源.我有以下两个类A,B它们都转发声明,struct Foo但cpp文件定义了如下的实际结构.

// This is A.h
namespace app {
    struct Foo;
    class A {
    private:
        std::vector<Foo> fooList;
    };
}

// This is A.cpp
struct app::Foo {
    std::string first;
    std::string second;
    unsigned flag;
};


// This is B.h
namespace app {
    struct Foo;
    class B {
    private:
        std::vector<Foo> fooList;
    };
}

// This is B.cpp
struct app::Foo {
    std::string first;
    std::string second;
    bool flag;
    float value;
};
Run Code Online (Sandbox Code Playgroud)

请注意,结构Foo在cpp文件中具有不同的成员A.cpp,B.cpp.这些类AB从未暴露成员fooList.是否有可能由于前向声明完全相同,在文件A.hB.h结构中Foo,生成的代码可能正在使用其中一个.这可以解释我在链接问题中看到的问题.

换句话说,虽然对于Foo调用的结构使用了braced-init-list,但是B.cpp它是否可以保证使用Foo定义的内容,B.cpp或者同样可能使用Foo定义的内容A.cpp

即使在我写这篇文章时,我立即意识到这种实现是一种不好的做法,因为Foo它本身就是类的内部A,B并且应该真正在类本身的私有部分中声明.

Yak*_*ont 9

这违反了ODR(一个定义规则).

该计划格式错误,无需诊断.

如果你这样做,那么C++标准绝对允许任何行为.它可以"工作",它可以选择一个并丢弃另一个,它可以工作,直到你重新链接,它可以格式化你的硬盘.

我在一个真实的现场项目中做到了这一点; 我们有一个矩阵标题,您可以在包含它之前定义标记,如果它支持float或double.

这"工作",而我们从未在同一个DLL中使用这两个版本.然后我们使用了两个版本.

编译器将根据一组巧合为结构选择一种尺寸或另一种尺寸,并根据略微不同的一组巧合选择一个构造函数或其他构造函数.我们的内存腐败很多.但有时只在某些版本上.

我们通过将代码包装在名称中包含标量类型的命名空间中来快速"修复"它,然后using将它们带入外部命名空间.