这是对另一个问题的后续。
原问题存在其他问题,但我不得不意识到主要问题(根据CLang)是在仅使用好的C++包含文件的情况下将time
重新定义为另一个符号。
因此,这里有一个简化版本:
#include<iostream>
using std::cout;
using std::endl;
class time
{
public:
int h, min, sec;
};
const int full = 60;
void canonify(time& pre) // Error here (line 14)
{
pre.min += pre.sec / full;
pre.h += pre.min / full;
pre.sec %= full;
pre.min %= full;
}
int main()
{
time a; // and here (line 23)
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(a);
cout << a.h << ":" << a.min << ":" << a.sec << endl;
}
当然,将time
替换为不同的符号或使用struct time
就足以解决问题。换句话说,我的问题并不是如何使代码运行,而只是我们是否必须将来自C库的符号视为C ++中的保留标记。
Clang 11(在MSVC19上)会出现错误:1>ess.cpp(14,15): error : must use 'class' tag to refer to type 'time' in this scope
1>...\ucrt\time.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
1>ess.cpp(23,5): error : must use 'class' tag to refer to type 'time' in this scope
1>...\ucrt\time.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
那么问题是:C++标准在何处禁止在编译单元中未明确包含的情况下自由使用来自C标准库的符号?
有趣的是,同样的代码(一旦被翻译...)在C中可以正常工作:
#include <stdio.h>
//
typedef struct
{
int h, min, sec;
}time;
//
const int full = 60;
//
void canonify(time* pre)
{
pre->min += pre->sec / full;
pre->h += pre->min / full;
pre->sec %= full;
pre->min %= full;
}
int main()
{
time a;
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(&a);
printf("%d:%d:%d\n", a.h, a.min, a.sec);
return 0;
}
std::endl
在这里完全是多余的。从main
返回将刷新std::cout
。通常情况下,在打印'\n'
时无需强制刷新 - 在 stdout 是 TTY 的情况下,cout 通常已经是行缓冲的,因此不需要额外操作。 - Peter Cordesiostream
可以并且确实从ctime
中公开符号,但是stdio.h
在编译为 C 时可能不会从time.h
中公开符号。 - zwol