Dam*_*hev 1 c++ visual-studio visual-c++ c++17
我有两个独立的编译单元,没有任何头文件:
\n单元a.cpp:
\n#include <algorithm>\n#include <vector>\nclass my_predicate\n{\n    const std::vector<int>& vec;\npublic:\n    my_predicate(const std::vector<int>& container) : vec(container) { }\n\n    bool operator() (size_t idx1, size_t idx2)\n    {\n        return vec[idx1] < vec[idx2];\n    }\n};\n\nint main()\n{\n    std::vector<int> v1,v2;\n    v1.resize(10);\n    v2.resize(10);\n\n    std::sort(v1.begin(), v1.end(), my_predicate(v2));\n}\n单元b.cpp:
\n#include <algorithm>\n#include <vector>\n\nclass my_predicate\n{\n    const std::vector<char>& vec;\npublic:\n    my_predicate(const std::vector<char>& container) : vec(container) { }\n\n    bool operator() (size_t idx1, size_t idx2)\n    {\n        std::cout << "Why the operator from b.cpp is called?" << std::endl;\n        return vec[idx1] < vec[idx2];\n    }\n};\n\nvoid bar()\n{\n    std::vector<char> v1, v2;\n\n    std::sort(v1.begin(), v1.end(), my_predicate(v2));\n}\n实现上的主要区别my_predicate在于所使用的容器类型:vector<int>和vector<char>。
正式来说,单元 a.cpp 应该对类一无所知my_predicate。
奇怪的事情开始于sort当main from a.cpp 执行
my_predicate它从a.cpp 中operator()从b.cppmy_predicate中调用调用它必须知道的\xe2\x80\x99。这也会在调试模式下重现,因此此处关闭了整个程序优化。
\n我是否遗漏了一些东西,现在类定义全局可见,或者这是一个编译器错误?
\n仅当我有一个虚拟调用时,魔法才会发生my_predicate(请参阅 b.cpp 中的虚拟未使用函数栏)。
作为奖励,如果我尝试重命名my_predicate使用 VS 重命名工具(Ctrl+R、Ctrl+R)在 a.cpp 中重命名,它会在两个文件中重命名它。
您bool my_predicate::operator()在两个翻译单元中进行了不同的定义,因此您的链接器可以选择其中任何一个 - 或拒绝重新定义。实际的类定义也不同,因此这是另一个 ODR 违规。
在g++
g++ -o x a.o b.o
使其使用 , 中的定义a.o,并且
g++ -o x a.o b.o
使其使用 中的定义b.o。
请参阅定义和 ODR(单一定义规则)。
为了在实现 ( .cpp) 文件中创建类(和函数等)时不导致这些类型的 ODR 违规,请将它们放入匿名命名空间中。
g++ -o x b.o a.o
// a.cpp
namespace { // anonymous namespace
class my_predicate {
    // a's definition
};
} // anonymous namespace
| 归档时间: | 
 | 
| 查看次数: | 110 次 | 
| 最近记录: |