英文:
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访问
英文:
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 "a.h"
class className {
public:
int functionB(const int & val) { // functionB uses functionA
return functionA(val);
}
};
// file: Source.cpp
#include "b.h"
int main() {
className obj;
obj.functionB(); // All good But,
functionA(); // I don't want main to access a.h'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 <cmath> header's function
#include <cmath>
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 <cmath>
}
}; // class ComplexNumber
} // namespace math
// Main.cpp
#include "ComplexNumbers.h"
#include <iostream>
using namespace std;
int main() {
math::ComplexNumber z(1,2); // Obj, All good But,
cout << atan(1) <<'\n'; // atan() function also works in main.cpp
return 0;
}
I don't want main.cpp to access <cmath> function via ComplexNumbers.h. Is there any way that the <cmath>'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 #include
s 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 export
s 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 <cmath>
instead of #include <cmath>
, 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 "a.h"
class className {
public:
int functionB(const int & 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 <cmath>
, you cannot do this, because you don't control what namespace the functions in <cmath>
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 "a.h"
would no longer need to appear in b.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);
}
In the context of <cmath>
, 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 <cmath>
into headers which use complex numbers. It's likely that users would have included the math library themselves.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论