A header file included in another header file. while including one of the files in main.cpp, both get included. how to prevent this?

huangapple go评论74阅读模式
英文:

A header file included in another header file. while including one of the files in main.cpp, both get included. how to prevent this?

问题

例如,假设有"a.h"、"b.h"和"source.cpp"这些文件。

// 文件:a.h
int functionA(int value) {
    ...
    return something
}

a.h是头文件。b.h使用a.h中的functionA。

// 文件:b.h
#include "a.h";

class className {
public:
    int functionB(const int & val) {        // functionB使用functionA
        return functionA(val);
    }
};
// 文件:Source.cpp
#include "b.h";

int main() {
    className obj;
    obj.functionB();        // 一切正常,但是,
    functionA();         // 我不想让main访问a.h中的函数
    return 0;
}

我不希望Source文件访问a.h中的函数。有没有办法限制source.cpp访问a.h中的函数。

这是我一直在尝试做的事情。
考虑ComplexNumbers.h和main.cpp。

// ComplexNumbers.h使用<cmath>头文件的函数
#include <cmath>

namespace math {
class ComplexNumber {
private:
    double real, imag;
public:
    ComplexNumber(double r, double i) {
        real = r;
        imag = i;
    }
    double getArgument() {        // 返回复数与x轴所成的角度
        return atan(imag/real);    // 使用<cmath>中的函数
    }
};  // class ComplexNumber
}   // namespace math
// Main.cpp
#include "ComplexNumbers.h"
#include <iostream>
using namespace std;

int main() {
    math::ComplexNumber z(1,2);    // 对象,一切正常,但是,
    cout << atan(1) << '\n';  // atan()函数也在main.cpp中工作
    return 0;
}

我不希望main.cpp通过ComplexNumbers.h访问函数。有没有办法让中的函数只在ComplexNumbers.cpp中使用,而不在main.cpp中使用。

英文:

For example, Let's suppose there are "a.h", "b.h" and "source.cpp"

// file: a.h
int functionA(int value) {
    ...
    return something
}

a.h is the header file. b.h uses functionA from a.h

// file: b.h
#include &quot;a.h&quot;

class className {
public:
    int functionB(const int &amp; val) {        // functionB uses functionA
        return functionA(val);
    }
};
// file: Source.cpp
#include &quot;b.h&quot;

int main() {
    className obj;
    obj.functionB();        // All good But,
    functionA();         // I don&#39;t want main to access a.h&#39;s function
    return 0;
}

I don't want the Source file to access a.h's functions. Is there any way to restrict source.cpp from accessing functions from a.h

Here's what I've been trying to do.
Consider ComplexNumbers.h and main.cpp

// ComplexNumbers.h uses &lt;cmath&gt; header&#39;s function
#include &lt;cmath&gt;

namespace math {
class ComplexNumber {
private:
    double real, imag;
public:
    ComplexNumber(double r, double i) {
        real = r;
        imag = i;
    }
    double getArgument() {        // returns the angle made by the complex number with x-axis
        return atan(imag/real);    // Uses function from &lt;cmath&gt;
    }
};  // class ComplexNumber
}   // namespace math
// Main.cpp
#include &quot;ComplexNumbers.h&quot;
#include &lt;iostream&gt;
using namespace std;

int main() {
    math::ComplexNumber z(1,2);    // Obj, All good But,
    cout &lt;&lt; atan(1) &lt;&lt;&#39;\n&#39;;  // atan() function also works in main.cpp
    return 0;
}

I don't want main.cpp to access &lt;cmath&gt; function via ComplexNumbers.h. Is there any way that the &lt;cmath&gt;'s function only gets used in ComplexNumbers.cpp rather than main.cpp

答案1

得分: 2

没有办法限制source.cpp无法访问a.h中的函数,除非对你的代码进行一些重大更改。头文件被“复制粘贴”到包含它们的文件中,没有办法使其中的某些部分无法访问。

考虑使用C++20模块

为了解决这个问题,你可以考虑使用C++20模块,它们只会使export可见,并允许你在不使导入的内容对其他模块可见的情况下导入其他模块。然而,C++20模块仍然有些不稳定,而且clang不支持它们,所以你可能不想使用它们。

在你的情况下,这将需要使用import <cmath>代替#include <cmath>,并且会产生期望的效果。

使用详细命名空间的解决方案

人们通常使用的一种“临时解决方案”是使用“详细命名空间”:

// 文件:a.h
namespace detail {

int functionA(int value) {
    ...
    return something
}

} // namespace detail

// 文件:b.h
#include "a.h"

class className {
public:
    int functionB(const int & val) {
        return detail::functionA(val);
    }
};

然而,这并不能防止在包含b.h时有人使用detail::functionA,它只是使人们不会意外使用它,而且该函数不会出现在自动完成中。

<cmath>的上下文中,你无法这样做,因为你无法控制<cmath>中的函数在哪个命名空间中。

使用源文件中的定义的解决方案

你也可以通过在源文件中实现functionB来解决这个问题。如果你这样做了,那么b.h中就不再需要出现#include "a.h"了:

// b.h
class className {
public:
    int functionB(const int & val);
};

// b.cpp
#include "b.h"
#include "a.h"

int className::functionB(const int & val) {
    return functionA(val);
}

<cmath>的上下文中,这将要求在源文件中实现ComplexNumber的成员函数,这是极不可取的,因为它会阻止内联和constexpr

结论

总之,有一些解决方案,但它们都有很大的缺点。然而,将#include <cmath>“泄漏”到使用复数的头文件中并不那么糟糕。用户很可能已经自己包含了数学库。

英文:

> Is there any way to restrict source.cpp from accessing functions from a.h

Not without some significant changes to your code. Headers are "copied and pasted" into the file that #includes them, and there is no way to make portions of them inaccessible.

Consider using C++20 modules

To solve this, you could be using C++20 modules, which only make exports visible, and allow you to import other modules without making the imported contents visible to other modules. However, C++20 modules are still somewhat unstable, and they're not supported by clang, so you might not want to use them.

In your case, this would require import &lt;cmath&gt; instead of #include &lt;cmath&gt;, and would have the desired effect.

Solution using detail namespaces

A "bandaid" solution that people typically use is a "detail namespace":

// file: a.h
namespace detail {

int functionA(int value) {
    ...
    return something
}

} // namespace detail

// file: b.h
#include &quot;a.h&quot;

class className {
public:
    int functionB(const int &amp; val) {
        return detail::functionA(val);
    }
};

However, this doesn't prevent someone from using detail::functionA when they include b.h, it just makes it so they don't accidentally use it, and the function won't show up for auto-completion.

In the context of &lt;cmath&gt;, you cannot do this, because you don't control what namespace the functions in &lt;cmath&gt; are in.

Solution using definitions in source files

You might also be able to solve this by implementing functionB in a source file. If you did that, then #include &quot;a.h&quot; would no longer need to appear in b.h:

// b.h
class className {
public:
    int functionB(const int &amp; val);
};


// b.cpp
#include &quot;b.h&quot;
#include &quot;a.h&quot;

int className::functionB(const int &amp; val) {
    return functionA(val);
}

In the context of &lt;cmath&gt;, this would require implementing member functions of ComplexNumber in a source file, which is extremely undesirable because it prevents inlining and constexpr.

Conclusion

In conclusion, there are some solutions, but all of them have major downsides. However, it's not that bad to "leak" the #include &lt;cmath&gt; into headers which use complex numbers. It's likely that users would have included the math library themselves.

huangapple
  • 本文由 发表于 2023年7月13日 17:54:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76678100.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定