【发布时间】:2011-04-12 02:20:36
【问题描述】:
在 Java 中,它们具有包访问说明符,它使该函数只能由来自同一个“包”(命名空间)的类使用,我看到了它的好处。尤其是在模型设计发挥作用时。你认为这样的东西在 C++ 中可能有用吗?
谢谢。
【问题讨论】:
标签: c++ language-features
在 Java 中,它们具有包访问说明符,它使该函数只能由来自同一个“包”(命名空间)的类使用,我看到了它的好处。尤其是在模型设计发挥作用时。你认为这样的东西在 C++ 中可能有用吗?
谢谢。
【问题讨论】:
标签: c++ language-features
晚了“一点点”,但万一其他人降落在这里......;)
有一个在 C++ 中模拟包的解决方案:利用内部类(也称为帮助类)的特殊性,它能够访问其外部类的任何成员,甚至是私有成员。
例子:
class Package
{
public:
class Public;
private:
class Private;
};
这里有一个完整的例子(及其permalink):
#include <iostream>
// Package.hpp
class Package
{
public:
Package () = delete;
class PublicClass;
private:
class PrivateClass;
};
// PrivateClass.hpp / cpp
class Package::PrivateClass
{
public:
PrivateClass ()
{
std::cout << "PrivateClass only usable by Package classes.\n";
}
private:
void Forbidden () {}
};
// PrivateClass.hpp / cpp
class Package::PublicClass
{
public:
PublicClass ()
{
std::cout << "PublicClass usable from outside/inside Package.\n";
Package::PrivateClass privateClass;
// privateClass.Forbidden (); // error: 'Forbidden' is a private member of 'Package::PrivateClass'
}
};
// main.cpp
int main ()
{
// Package package; // error: call to deleted constructor of 'Package'.
Package::PublicClass publicClass;
//Package::PrivateClass privateClass; // error: 'PrivateClass' is a private member of 'Package'
return EXIT_SUCCESS;
}
// Output:
// -------
// PublicClass usable from outside/inside Package.
// PrivateClass only usable by Package classes.
【讨论】:
正如其他人指出的那样,通常的做法只是按照惯例,但是 C++ 确实提供了friends,它允许您指定只有您指定的类/函数才能访问类的内部,例如私有函数,这可用于提供类似包的限制。
在 C++ 中避免使用大多数朋友,因为它们往往会增加耦合
实际上并没有直接的等价物,因为 C++ 不是例如旨在应对移动代码,:.无论如何,访问说明符是一种方便而不是安全功能。
【讨论】:
您可以为“包”的用户提供一个应该是“公共”的头文件。只能在内部使用的东西可以将它们的头文件放在一个名为“内部”或(包名)的文件夹中。这不会阻止某人实际包含这些文件,但您传达他不应该包含这些文件!
【讨论】:
是的,这可以实现。您可以通过公共、受保护、私有关键字以及源可见性来限制可见性。
声明的可见性是普遍理解的。
源代码可见性(如果您来自 Java)有点不同。
Java:您有一个用于对象接口/实现的文件。 Cpp:你有一个接口文件。实现可能位于接口中,也可能位于一个或多个实现(cpp、cxx)文件中。
如果您使用除了库的公共接口之外的抽象类/接口/函数,它们实际上是隐藏的并且不可访问(好吧,如果您有特别爱管闲事的用户转储符号,这是错误的——那么他们可能会重新声明接口,并链接到符号,但是......这显然是他们未定义的领域)。所以你只需要让你喜欢的符号可见。使用包/库命名约定来避免链接错误是一个好主意 - 将类放在为库的私有实现保留的命名空间中。很简单。
它在 C++ 中有用吗...还不错,尽管我个人认为该语言有更高的优先级。
源可见性示例:
/* publicly visible header file */
namespace MON {
class t_button {
protected:
t_button();
virtual ~t_button();
public:
typedef enum { Default = 0, Glowing = 1 } ButtonType;
/* ... all public virtual methods for this family of buttons - aka the public interface ... */
public:
t_button* CreateButtonOfType(const ButtonType& type);
};
}
/* implementation file -- not visible to clients */
namespace MON {
namespace Private {
class t_glowing_button : public t_button {
public:
t_glowing_button();
virtual ~t_glowing_button();
public:
/* ... impl ... */
};
}
}
MON::t_button* MON::t_button::CreateButtonOfType(const ButtonType& type) {
switch (type) {
case Glowing :
return new Private::t_glowing_button();
case Default :
return new Private::t_glowing_button();
/* .... */
default :
break;
}
/* ... */
return 0;
}
【讨论】:
一个Java包大致是:
在 C++ 中,第一个可以通过明智地使用 namespace 来实现。但是,没有办法使用语言结构来模拟后者。
【讨论】:
在 C++ 中,如果需要,请使用类。
IMO,访问规则已经足够复杂了。
(请注意,您可以拥有只包含 static 成员函数的类,从而有效地实现您想要的。)
【讨论】:
class 用作namespace。 (当然,这样做的缺点是命名空间是开放的,而类则不是。)