简体   繁体   English

C ++命名空间和模板

[英]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. 最后,我决定使用类,以便代码更具可移植性,可重用性和通用性。

  • classes allows one to do all sorts of meta-programming like traits, tag dispatching and policies. 类允许人们进行各种元编程,如特征,标签调度和策略。
  • classes already have public, private and protected. 课程已经有公共,私人和受保护。

the only two reasons why you would use namespace: 您使用命名空间的唯一两个原因:

  • to resolve naming conflicts std::for_each vs boost::for_each 解决命名冲突std::for_each vs boost::for_each
  • to reduce visual noise. 减少视觉噪音。 for example 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM