Visual Studio Visual C++:为什么调用来自不同编译单元的类方法?

bq3bfh9z  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(164)

我有两个独立的编译单元,没有任何头文件:
单位a.cpp:

  1. #include <algorithm>
  2. #include <vector>
  3. class my_predicate
  4. {
  5. const std::vector<int>& vec;
  6. public:
  7. my_predicate(const std::vector<int>& container) : vec(container) { }
  8. bool operator() (size_t idx1, size_t idx2)
  9. {
  10. return vec[idx1] < vec[idx2];
  11. }
  12. };
  13. int main()
  14. {
  15. std::vector<int> v1,v2;
  16. v1.resize(10);
  17. v2.resize(10);
  18. std::sort(v1.begin(), v1.end(), my_predicate(v2));
  19. }

单位B.cpp:

  1. #include <algorithm>
  2. #include <vector>
  3. class my_predicate
  4. {
  5. const std::vector<char>& vec;
  6. public:
  7. my_predicate(const std::vector<char>& container) : vec(container) { }
  8. bool operator() (size_t idx1, size_t idx2)
  9. {
  10. std::cout << "Why the operator from b.cpp is called?" << std::endl;
  11. return vec[idx1] < vec[idx2];
  12. }
  13. };
  14. void bar()
  15. {
  16. std::vector<char> v1, v2;
  17. std::sort(v1.begin(), v1.end(), my_predicate(v2));
  18. }

my_predicate实现的关键区别在于使用的容器类型:vector<int>vector<char>
形式上,单元a.cpp应该不知道来自单元b.cpp的类my_predicate
奇怪的事情开始于sort in main from a.cpp被执行:
1.它从a.cpp中的my_predicate调用正确的构造函数
1.然后为了排序,突然开始从B.cpp中的my_predicate调用operator(),这是它不知道的。
这也是在优化模式下重现的,所以在这里关闭了整个程序优化。
我错过了什么,现在类定义全局可见,或者这是一个编译器错误?
只有当我在b.cpp中对my_predicate有一个伪调用时,魔法才会发生(参见b.cpp中的伪未使用函数栏)。
作为奖励,如果我尝试在a.cpp中使用VS重命名工具(Ctrl+R,Ctrl+R)重命名my_predicate,它会在两个文件中重命名它。

c86crjj0

c86crjj01#

您在两个翻译单元中以不同的方式定义了bool my_predicate::operator(),因此您的链接器可以选择其中任何一个-或者拒绝重新定义。实际的类定义也是不同的,所以这是另一个ODR冲突。
单位:g++

  1. g++ -o x a.o b.o

使用a.o中的定义,

  1. g++ -o x b.o a.o

使用b.o中的定义。
请参见Definitions and ODR (One Definition Rule)
为了在实现(.cpp)文件中创建类(和函数等)时不导致这些类型的ODR违规,请将它们放在匿名名称空间中。

  1. // a.cpp
  2. namespace { // anonymous namespace
  3. class my_predicate {
  4. // a's definition
  5. };
  6. } // anonymous namespace
  1. // b.cpp
  2. namespace { // anonymous namespace
  3. class my_predicate {
  4. // b's definition
  5. };
  6. } // anonymous namespace
展开查看全部

相关问题