22

我对私有方法和函数有疑问。假设我有一些不需要在类中的实用方法。但是这些相同的方法需要调用我不想向用户公开的其他方法。例如:

嫌疑人.h

namespace Suspect {
  /**
  *  \brief This should do this and that and more funny things.
  */
  void VerbalKint(void);  // This is for you to use
}

嫌疑人.cpp

namespace Suspect {
  namespace Surprise {
    /**
    * \brief The user doesn't need to be aware of this, as long 
    *        the public available VerbalKint does what it should do.
    */
    void KeyserSoze(void) {
      // Whatever
    }
  } // end Surprise

  void VerbalKint(void) {
    Surprise::KeyserSoze();
  }
}

所以,这个布局有效。包含 时Suspect.h,只有VerbalKint可见。这也可以使用类和标记VerbalKint为静态来实现:

class Suspect {
public:
  // Whatever
  static void VerbalKint(void);
private:
  static void KeyserSoze(void);
};

我想知道这两种方法之间是否有任何区别。一个比另一个更好(更快、更容易维护)吗?

你觉得呢?你有没有什么想法?

4

4 回答 4

16

如果函数是“免费的”,您应该在以下位置使用匿名命名空间*.cpp

namespace Suspect {
namespace Surprise {
namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon
} // end Surprise
} // end Suspect

甚至:

namespace {
    void KeyserSoze(void) {
      // Whatever
    }
} // end anon

这使它远离客户端,因此他们在链接时无法访问、依赖或与您的导出冲突。如果定义可见,它还可以保留不必要的声明,从而减少它们的编译时间和潜在的链接时间或二进制大小。最后,它使它成为私有的,因此他们不能依赖它,并且您不需要维护它以供他们使用。KeyserSoze()如果您选择(在's 的情况下为函数指针),您仍然可以将这些传递给外界。

在其他时候,最好在您的类中声明一个私有成员函数,然后在*.cpp(如果可能)中定义它。通常,当您需要与班级建立更密切的关系时(例如,当您需要访问某些成员时),您会选择这种方法。你说问题中不是这种情况,但我只是重申何时应该使用私人成员。

于 2013-05-29T12:37:56.323 回答
10

最好的方法是在一个未命名的命名空间中定义所有辅助函数Suspect.cpp,而不是在Suspect::Surprise命名空间中。

在您的情况下,这将是:

namespace{
void KeyserSoze(){ ... };
}

您可以简单地KeyserSozeSuspect.cpp.

您可以在此处找到更多信息:未命名/匿名命名空间与静态函数

另一种选择是声明KeyserSozestatic,但标准不建议这样做。C++ 标准在第 7.3.1.1 节未命名命名空间,第 2 段中写道:

在命名空间范围内声明对象时,不推荐使用 static 关键字,未命名命名空间提供了更好的选择

于 2013-05-29T12:11:28.393 回答
5

实际上,即使您没有在任何标题中声明该函数,眼睛也看不到它;如果用户编写声明,它仍然可供用户使用。

在 C++ 中,隐藏在文件级别声明的符号的机制是:

  • static用于(全局)变量和函数
  • namespace { ... }(匿名命名空间)任何你想要的东西(更通用,更详细)

例如:

// Suspect.cpp

namespace Suspect {

    static void KeyserSore() {}

    void VerbalKing() { KeyserSore(); }

}
于 2013-05-29T12:14:42.990 回答
2

将某些内容放入类或命名空间之间的主要区别在于,您不能将额外的静态函数添加到另一个头文件中的类中。

这个:啊

namespace Fred {
   void Somefunc();
}

bh

namespace Fred {
   void Anotherfunc();
}

工作,尽管 a 和 b 都不知道彼此对他们的命名空间做了什么。这可能会导致问题,例如:

ch

namespace Fred {
   void Thirdfunc();
}

dh

namespace Fred {
   bool Thirdfunc();
}

在你开始运行程序之前,这一切都很好而且很花哨......

这虽然不是不可能的,但在课堂上的可能性要小得多。

在您的示例中,只有一个源文件,您可能还需要考虑使用匿名命名空间,因为它将声明限制在文件范围内,因此文件外的人无法意外访问它们(或与它们发生冲突)。

于 2013-05-29T12:18:03.820 回答