[英]C++ Namespaces & templates
I have some functions that can be grouped together, but don't belong to some object / entity and therefore can't be treated as methods. 我有一些功能可以组合在一起,但不属于某个对象/实体,因此不能被视为方法。
So, basically in this situation I would create a new namespace and put the definitions in a header
file, the implementation in cpp
file. 所以,基本上在这种情况下我会创建一个新的命名空间并将定义放在
header
文件中,在cpp
文件中实现。 Also (if needed) I would create an anonymous namespace in that cpp
file and put all additional functions that don't have to be exposed / included to my namespace's interface there. 另外(如果需要)我将在该
cpp
文件中创建一个匿名命名空间,并将所有其他不需要公开/包含的函数放在我的命名空间接口中。
See the code below (probably not the best example and could be done better with another program architecture, but I just can't think of a better sample...) 请参阅下面的代码(可能不是最好的示例,可以使用其他程序架构更好地完成,但我想不出更好的示例...)
Sample code ( header
) 示例代码(
header
)
namespace algorithm {
void HandleCollision(Object* object1, Object* object2);
}
Sample code ( cpp
) 示例代码(
cpp
)
#include "header"
// Anonymous namespace that wraps
// routines that are used inside 'algorithm' methods
// but don't have to be exposed
namespace {
void RefractObject(Object* object1) {
// Do something with that object
// (...)
}
}
namespace algorithm {
void HandleCollision(Object* object1, Object* object2) {
if (...) RefractObject(object1);
}
}
So far so good. 到现在为止还挺好。 I guess this is a good way to manage my code, but I don't know what should I do if I have some template-based functions and want to do basically the same.
我想这是管理我的代码的好方法,但我不知道如果我有一些基于模板的函数并且想要做的基本相同,我该怎么办。
If I'm using templates, I have to put all my code in the header
file. 如果我使用模板,我必须将所有代码放在
header
文件中。 Ok, but how should I conceal some implementation details then? 好的,但是我应该如何隐藏一些实现细节呢?
I want to hide RefractObject
function from my interface, but I can't simply remove its declaration (just because I have all my code in a header
file)... 我想从我的界面隐藏
RefractObject
函数,但我不能简单地删除它的声明(因为我在header
文件中有我所有的代码)...
The only approach I came up with was something like: 我提出的唯一方法是:
Sample code ( header
) 示例代码(
header
)
namespace algorithm {
// Is still exposed as a part of interface!
namespace impl {
template <typename T>
void RefractObject(T* object1) {
// Do something with that object
// (...)
}
}
template <typename T, typename Y>
void HandleCollision(T* object1, Y* object2) {
impl::RefractObject(object1);
// Another stuff
}
}
Any ideas how to make this better in terms of code designing? 任何想法如何在代码设计方面做得更好?
That's a pretty common solution. 这是一个非常常见的解决方案。 Boost does it, and I do it as well, but with the
detail
namespace instead. Boost做到了,我也这样做,但是使用了
detail
命名空间。 Just make it a rule: "don't look inside detail
!" 让它成为一个规则:“不要看内部
detail
!”
File-wise, I recommend giving details their own file, and tucking it away in a detail folder. 文件方面,我建议提供他们自己的文件的详细信息,并将其放在详细文件夹中。 That is, my code would be akin to:
也就是说,我的代码类似于:
// v
#include "detail/RefractObject.hpp"
namespace algorithm {
template <typename T, typename Y>
void HandleCollision(T* object1, Y* object2) {
detail::RefractObject(object1);
// Another stuff
}
}
This is just good code practice in general (keep things split up and re-usable) and keeps the header file cleaner of implementation details. 这只是一般的良好代码实践(保持分离和可重用)并使头文件更清晰的实现细节。
Build a "static class"- instead of the namespace, declare a class with the same name. 构建一个“静态类” - 而不是命名空间,声明一个具有相同名称的类。 Make the constructor, destructor, copy, and assignment operators private, then make every one of your stand-alone functions a static member function.
使构造函数,析构函数,复制和赋值运算符成为私有,然后使每个独立函数成为静态成员函数。
A template Example: 模板示例:
template<class T>
class StringOperator
{
friend SomeOtherLibraryClass; // Let it use "Hidden()"
private:
StringOperator() {}
~StringOperator() {}
StringOperator(const StringOperator&);
StringOperator& operator=(const StringOperator&);
static bool Hidden(const T& input) {
// Hidden routine end-users shouldn't see...
}
public:
static void YourFunction(T& parameter) {
// Some public code....
}
static T AnotherRoutine(const T* ptr) {
// Some public code...
}
};
Here are some advantages vs. a namespace: 以下是命名空间的一些优点:
1) You can template the entire class, ensuring that you have a version of every function for every type- you could even specialize to add/remove functions based on type. 1)您可以模拟整个类,确保您拥有每种类型的每个函数的版本 - 您甚至可以专门根据类型添加/删除函数。
2) You have a private area where you can hide the declarations for the non-public objects and methods you need 2)您有一个私有区域,您可以在其中隐藏所需的非公共对象和方法的声明
3) Through the "friend" mechanism, you can let other objects like "SomeOtherLibraryClass" use your functions without exposing them to end users. 3)通过“朋友”机制,您可以让“SomeOtherLibraryClass”等其他对象使用您的功能,而不会将它们暴露给最终用户。
End users can access the functions with "StringOperator::FunctionName()", or you could template the functions instead to provide "StringOperator::FunctionName()". 最终用户可以使用“StringOperator :: FunctionName()”访问函数,或者您可以模拟函数来提供“StringOperator :: FunctionName()”。 The latter is the same pattern they'd use to access functions in a namespace.
后者与用于访问命名空间中的函数的模式相同。
You can't hide your source from the user unless you're going to compile it first, which is impossible with templates. 除非您要先编译它,否则您无法向用户隐藏源代码,这对于模板来说是不可能的。 So I suggest, in a sense, that you don't bother.
从某种意义上说,我建议你不要打扰。
Also gotta ask why Refract can't be a member method. 还要问为什么Refract不能成为成员方法。
i thought about the same thing for a while. 我想了一会儿同样的事情。 in the end, i decided to use classes so that the code is more portable, reusable and general.
最后,我决定使用类,以便代码更具可移植性,可重用性和通用性。
the only two reasons why you would use namespace: 您使用命名空间的唯一两个原因:
std::for_each
vs boost::for_each
std::for_each
vs boost::for_each
using namespace boost::filesystem
, would let you just call its function without ::
. using namespace boost::filesystem
,只需调用其函数而不使用::
。 even for these two cases, you can either inherit the class that has the methods or rename by initiating ( my_own_filesystem_methods fs;
and us it as fs.mkdir()
. plus, .
is shorter than ::
. 即使对于这两种情况下,你可以继承有方法的类或通过启动(重命名
my_own_filesystem_methods fs;
而我们作为fs.mkdir()
再加上, .
比短::
。
there are other benefits of namespaces like std::cout << "hi" << endl;
命名空间还有其他好处,比如
std::cout << "hi" << endl;
but it's not very important. 但这不是很重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.