1

所以,我正在做一个项目,我打算在没有必须使用 Visual Studio 2015 或 2017 的 math.h 或 cmath 库帮助的情况下实现我自己版本的三角函数、平方根、舍入和指数. 我习惯于使用 GCC,当没有明确包含 math.h 或 cmath 时,它们各自的函数没有链接。在我新安装的空的、仅包含 iostream 的 Visual Studio 项目中,我似乎获得了使用 sin、cos 和 tangent 函数的能力,以及重复声明函数的错误。此后,我在两台计算机上新建了一个虚拟项目(一台是运行全新安装的 VS2017 的工作计算机,另一台是运行 VS2015 的个人计算机)并剥离了所有链接库,

#include <iostream>

int main()
{
    float n = sin(3.1415f);
    return 0;
};

在我的整个项目中。我不确定如何在没有链接到外部文件的情况下重建项目并且没有任何其他包含,我能够访问 sin() 函数。此外,如果我将文件更改为

#include <iostream>

float sin(float n)
{
    return 1.0f;
};

int main()
{
    float n = sin(3.1415f);
    return 0;
};

它向我展示了C2382。无论我的外部依赖项中是否包含其他文件,都会发生这种情况。在保持对 printf()、std::cout 和 system("PAUSE") 等基本功能的访问的同时,我将如何删除对 math.h 的包含?为了这个项目的目的,就像我在 GCC 环境中一样?

  • 可悲的是,尽管我一直在命名空间内进行开发以根据标准库检查我的实现,但我并不打算将标准数学函数与最终结果联系起来。这在 GCC 中很容易实现,但正如我所提到的,这个项目必须在 VS 中。
4

2 回答 2

2

如果您要实现自己的数学函数版本,那么最好将它们包装到您自己的命名空间中以避免名称冲突。

#include <iostream>

namespace n_my_math
{

float sin(float n)
{
    return 1.0f;
}

} // namespace n_my_math

int main()
{
    float n = n_my_math::sin(3.1415f);
    return 0;
};
于 2017-04-17T08:45:52.173 回答
1

任何标准库头文件都可以包含任何其他头文件;<cmath>在 VC++中,包含路径以iostream->istream->ostream->ios->xlocnum.

但是,通常包括 math.h/cmath 本身不应该是一个问题,只要您定义的替换具有相同的签名并且您不间接或以其他方式使用您未定义的任何接口。也就是说,您需要删除的不是 math.h - 这对于确保标准和您的实现之间的可比性很有用。相反,您需要做的是阻止链接器链接数学库(同时仍可能链接 C 库的其他部分。

不幸的是,这在 VC++ 中是不可能的,因为与 mlib 和 cstdlib 是独立库的 GCC 不同,在 VC++ 中,整个标准库是一个单一的实体。此外,C++ 标准库依赖于该库,因此您必须替换的不仅仅是数学函数,以避免链接标准库。

可以指示 VC++ 忽略默认库,如下所示:

在此处输入图像描述

但是标准库的整体性意味着它不会对您有太大帮助,因为即使是最简单的空main()代码也有许多其他依赖项,因为所有 C 运行时环境(GCC 中 crt0.o 中的那种东西) ) 包含在同一个库中。

您最好的方法是在它们自己的命名空间中继续使用您的函数——这毕竟是命名空间的用途。在您的库头文件中,您可以包含宏定义以避免链接标准数学函数:

#define sin mymath::sin

但这并不完全令人满意 - 如果您的标头包含任何包含 math.h 的标准标头之前(直接或间接),它可能无法链接甚至以难以理解的方式编译。

于 2017-04-17T09:49:06.467 回答