我有两个独立的编译单元,没有任何头文件:
单位a.cpp:
#include <algorithm>
#include <vector>
class my_predicate
{
const std::vector<int>& vec;
public:
my_predicate(const std::vector<int>& container) : vec(container) { }
bool operator() (size_t idx1, size_t idx2)
{
return vec[idx1] < vec[idx2];
}
};
int main()
{
std::vector<int> v1,v2;
v1.resize(10);
v2.resize(10);
std::sort(v1.begin(), v1.end(), my_predicate(v2));
}
单位B.cpp:
#include <algorithm>
#include <vector>
class my_predicate
{
const std::vector<char>& vec;
public:
my_predicate(const std::vector<char>& container) : vec(container) { }
bool operator() (size_t idx1, size_t idx2)
{
std::cout << "Why the operator from b.cpp is called?" << std::endl;
return vec[idx1] < vec[idx2];
}
};
void bar()
{
std::vector<char> v1, v2;
std::sort(v1.begin(), v1.end(), my_predicate(v2));
}
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
,它会在两个文件中重命名它。
1条答案
按热度按时间c86crjj01#
您在两个翻译单元中以不同的方式定义了
bool my_predicate::operator()
,因此您的链接器可以选择其中任何一个-或者拒绝重新定义。实际的类定义也是不同的,所以这是另一个ODR冲突。单位:
g++
使用
a.o
中的定义,使用
b.o
中的定义。请参见Definitions and ODR (One Definition Rule)。
为了在实现(
.cpp
)文件中创建类(和函数等)时不导致这些类型的ODR违规,请将它们放在匿名名称空间中。