gpt4 book ai didi

C++ 类名冲突

转载 作者:IT老高 更新时间:2023-10-28 13:57:31 31 4
gpt4 key购买 nike

对于以下 C++ 代码,我遇到了意外行为。该行为已通过最近的 GCC、Clang 和 MSVC++ 进行了验证。要触发它,需要将代码拆分到多个文件中。

def.h

#pragma once

template<typename T>
struct Base
{
void call() {hook(data);}
virtual void hook(T& arg)=0;
T data;
};

foo.h

#pragma once
void foo();

foo.cc

#include "foo.h"
#include <iostream>
#include "def.h"

struct X : Base<int>
{
virtual void hook(int& arg) {std::cout << "foo " << arg << std::endl;}
};


void foo()
{
X x;
x.data=1;
x.call();
}

bar.h

#pragma once
void bar();

bar.cc

#include "bar.h"

#include <iostream>
#include "def.h"

struct X : Base<double>
{
virtual void hook(double& arg) {std::cout << "bar " << arg << std::endl;}
};


void bar()
{
X x;
x.data=1;
x.call();
}

main.cc

#include "foo.h"
#include "bar.h"

int main()
{
foo();
bar();
return 0;
}

预期输出:

foo 1
bar 1

实际输出:

bar 4.94066e-324
bar 1

我预期会发生什么:

在 foo.cc 内部,创建了一个定义在 foo.cc 中的 X 的实例,并通过调用 call(),调用了 foo.cc 中的 hook() 的实现。酒吧也一样。

实际发生了什么:

在 foo.cc 中定义的 X 实例是在 foo() 中创建的。但是在调用 call 时,它不会调度到 foo.cc 中定义的 hook(),而是调度到 bar.cc 中定义的 hook()。这会导致损坏,因为 hook 的参数仍然是 int,而不是 double。

问题可以通过将 foo.cc 中的 X 定义放在 bar.cc 中的 X 定义之外的其他命名空间中来解决

所以最后的问题是:没有编译器警告。 gcc、clang 或 MSVC++ 都没有对此发出警告。按照 C++ 标准的定义,这种行为是否有效?

这种情况似乎有点虚构,但它发生在真实世界的场景中。我正在使用 rapidcheck 编写测试,其中对要测试的单元的可能操作被定义为类。大多数容器类都有类似的操作,因此在为队列和 vector 编写测试时,可能会多次出现名称为“Clear”、“Push”或“Pop”的类。由于这些仅在本地需要,因此我将它们直接放入执行测试的源中。

最佳答案

程序格式错误,因为它违反了 One-Definition Rule通过对类 X 有两个不同的定义。所以它不是一个有效的 C++ 程序。请注意,该标准特别允许编译器不诊断此违规行为。因此编译器符合要求,但程序不是有效的 C++,因此具有 Undefined Behaviour执行时(因此任何事情都可能发生)。

关于C++ 类名冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51154527/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com