【问题标题】:How to deal with math.h pollution in Visual Studio C++?如何处理 Visual Studio C++ 中的 math.h 污染?
【发布时间】:2012-09-08 17:52:22
【问题描述】:

在 Visual Studio 2012 中,我无法将某些名称声明为全局标识符,因为它们已在 math.h 中声明。遗留问题使我不方便重命名源代码中的标识符。除了重命名还有什么选择?

#include "stdafx.h"
// iostream includes math.h which declares the following
_CRT_NONSTDC_DEPRECATE(_y1) _CRTIMP double  __cdecl y1(_In_ double _X);

int y1; // error - y1 is already declared

void Main()
{
    return;
}

额外问题:Visual Studio 2012 是否以一致的方式处理此问题?

【问题讨论】:

  • 您确定iostream 包含math.h 而不是cmath?确保你不是using namespace std
  • iostream 最终包含 cmath,其中直接包含 math.h。
  • 不,cmath 保证在 std 命名空间中包含 math.h
  • 确实我是using namespace std。你提示我阅读stackoverflow.com/questions/1452721/…。我现在可以看出我是一个误入歧途的 C 程序员,没有理会命名空间课程。现已更正。
  • 您要我发布一个答案让您接受吗?

标签: c++ visual-studio namespaces standards-compliance


【解决方案1】:

因为这是 C++,你应该为你自己的东西使用一个命名空间,特别是如果你有全局变量。

#include "stdafx.h"

namespace MyApp
{
    int y1; // MyApp::y1
}

这样,您可以依赖 using 关键字,您需要使用不带命名空间名称的 y1 变量:

using MyApp::y1; // Now also y1

【讨论】:

  • OP 旁注:你确定void Main() 是正确的签名吗?通常它是int main(MS 的 cl 编译器可能期望 int _tmain)。
  • void Main() 是一个完全有效的函数声明(假设是区分大小写的链接器)。这不是程序的入口点。如果它打算作为入口点,那么它至少有两个问题。
  • @KeithThompson 我清楚地知道void Main() 是有效的(......真的吗?),但并不需要天才就能意识到他打算将其作为切入点。跨度>
  • 入口点确实是调用 void Main 的 int _tmain。使用 int _tmain 会更规范。使用 void Main 会导致分心。对不起。
  • @oldrinb:事实证明,他打算将void Main()作为入口点。
【解决方案2】:

标识符y1 可能出现在<math.h> 的某些版本中,但它不是由C 或C++ 标准定义的。您应该能够以一种避免声明y1 的方式调用编译器,可能是通过禁用语言扩展。如果编译器不允许你这样做,那就是实现中的错误。

y1() 是“第二类贝塞尔函数”之一(我不太确定这是什么意思)。我是specified by POSIX

【讨论】:

    【解决方案3】:

    正如我在 cmets 中所说,iostream 将不包括 math.h,而是包括 cmath。细微的区别在于cmath 将所有内容都放在std 命名空间中。问题是您正在执行以下操作...

    using namespace std;
    

    ... 不要。如您所见,您自己在全局命名空间中引入了歧义。相反,尝试从std 明确指定您需要的内容,而不是使用您包含的标头中声明的任何std 成员来污染全局命名空间。您还应该避免使用全局变量和全局命名空间本身。

    作为旁注,尝试显示整个代码,因为不清楚 _tmain 在这里调用了 Main

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 1970-01-01
      • 2013-01-14
      • 2013-08-25
      • 2011-02-05
      • 1970-01-01
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多