This is a question about what defining a class as public or private does.
这是关于将类定义为公共还是私有的问题。
Right now, I have various classes defined inside of a namespace and I only want some of those classes to be visible/usable to the outside world.
现在,我在命名空间内定义了各种类,我只希望其中一些类对外界可见/可用。
So, for example, if the classes below were the only ones in the program, I would want main.cpp to only be able to see/use the MyPublic class, not the MyPrivate class. I thought that defining the MyPrivate class as private and the MyPublic class as public would accomplish this, but the below code works and main.cpp is able to declare a MyPrivate object.
因此,例如,如果下面的类是程序中唯一的类,我希望main.cpp只能看到/使用MyPublic类,而不是MyPrivate类。我认为将MyPrivate类定义为private并将MyPublic类定义为public将实现此目的,但是下面的代码可以工作,main.cpp可以声明MyPrivate对象。
Is it possible to do this in C++?
是否可以在C ++中执行此操作?
MyPrivate.h:
namespace MyNamespace{
// only classes inside of the MyNamespace should be able
// to use this
private ref class MyPrivate{
...
};
}
MyPublic.h:
#include "MyPrivate.h"
namespace MyNamespace {
// anyone can declare this
public ref class MyPublic{
...
private:
MyNamespace::MyPrivate^ p;
...
};
}
Main.cpp:
#include "MyPublic.h"
int main(){
MyNamespace::MyPublic p_yes; // this is fine
MyNamespace::MyPrivate p_no; // don't want this to be possible
return 0;
}
4 个解决方案
#1
private/public in this situation will affect how classes are visible outside an assembly, if you want to create a class that is "private" in the meaning that it can be used only by some other class, you can use nested clas mechanism, like this:
private / public在这种情况下会影响类在程序集外可见的方式,如果你想创建一个“私有”的类,意思是它只能被其他类使用,你可以使用嵌套的clas机制,比如这个:
namespace MyNamespace { public ref class MyPublic { private: ref class MyPrivate { public: int x; }; MyPrivate^ p; }; }
//Edit: You can by the way still throw this nested class in public:
section and use it like this:MyNamespace::MyPublic::MyPrivate priv;
//编辑:顺便说一下,你仍然可以在public:section中抛出这个嵌套类,并像这样使用它:MyNamespace :: MyPublic :: MyPrivate priv;
#2
The private keyword means something else than you think. I limits visibility of the ref class beyond the assembly. Since your Main() method is in the same assembly, it has no trouble referencing the type name. Note that the C# language's "internal" keyword means the same thing.
private关键字意味着你想象的其他东西。我将ref类的可见性限制在程序集之外。由于您的Main()方法在同一个程序集中,因此引用类型名称没有任何问题。请注意,C#语言的“内部”关键字意味着相同的事情。
I assume that you really intend for these classes to be in a separate assembly someday. As such, using private is certainly good enough. Using nested private classes can make a class inaccessible to code in the same assembly.
我假设你真的打算让这些类有一天在一个单独的程序集中。因此,使用私有肯定是足够好的。使用嵌套的私有类可以使类在同一程序集中无法访问。
#3
You public header shouldn't include private header. Forward declare private class and include header only in MyPublic.cpp. Or that's what I'd say if you used normal C++. Bastardized .Net dialect might change things.
您的公共标头不应包含私有标头。转发声明私有类并仅在MyPublic.cpp中包含标头。或者,如果您使用普通的C ++,那就是我所说的。 Bastardized .Net方言可能改变一切。
#4
Unfortunately, the access modifiers on a class only affect visibility outside the assembly you're building. C++ doesn't support any sort of access modifiers that apply to namespaces in the way you're describing.
遗憾的是,类上的访问修饰符仅影响您正在构建的程序集之外的可见性。 C ++不支持以您描述的方式应用于命名空间的任何类型的访问修饰符。
A common idiom for simulating this is to put the "private" code into a detail
namespace (e.g. put it in MyNamespace::detail
). This is used a lot in e.g. the boost libraries. By convention, code in a detail namespace should only be used by code in the enclosing namespace (so MyNamespace::detail
should only be used by code in MyNamespace
), although the compiler won't enforce this for you.
模拟这个的常用习惯是将“私有”代码放入详细命名空间(例如将其放在MyNamespace :: detail中)。这在例如使用中很多。升级库。按照惯例,详细命名空间中的代码只能由封闭命名空间中的代码使用(因此MyNamespace :: detail应仅由MyNamespace中的代码使用),尽管编译器不会为您强制执行此操作。
#1
private/public in this situation will affect how classes are visible outside an assembly, if you want to create a class that is "private" in the meaning that it can be used only by some other class, you can use nested clas mechanism, like this:
private / public在这种情况下会影响类在程序集外可见的方式,如果你想创建一个“私有”的类,意思是它只能被其他类使用,你可以使用嵌套的clas机制,比如这个:
namespace MyNamespace { public ref class MyPublic { private: ref class MyPrivate { public: int x; }; MyPrivate^ p; }; }
//Edit: You can by the way still throw this nested class in public:
section and use it like this:MyNamespace::MyPublic::MyPrivate priv;
//编辑:顺便说一下,你仍然可以在public:section中抛出这个嵌套类,并像这样使用它:MyNamespace :: MyPublic :: MyPrivate priv;
#2
The private keyword means something else than you think. I limits visibility of the ref class beyond the assembly. Since your Main() method is in the same assembly, it has no trouble referencing the type name. Note that the C# language's "internal" keyword means the same thing.
private关键字意味着你想象的其他东西。我将ref类的可见性限制在程序集之外。由于您的Main()方法在同一个程序集中,因此引用类型名称没有任何问题。请注意,C#语言的“内部”关键字意味着相同的事情。
I assume that you really intend for these classes to be in a separate assembly someday. As such, using private is certainly good enough. Using nested private classes can make a class inaccessible to code in the same assembly.
我假设你真的打算让这些类有一天在一个单独的程序集中。因此,使用私有肯定是足够好的。使用嵌套的私有类可以使类在同一程序集中无法访问。
#3
You public header shouldn't include private header. Forward declare private class and include header only in MyPublic.cpp. Or that's what I'd say if you used normal C++. Bastardized .Net dialect might change things.
您的公共标头不应包含私有标头。转发声明私有类并仅在MyPublic.cpp中包含标头。或者,如果您使用普通的C ++,那就是我所说的。 Bastardized .Net方言可能改变一切。
#4
Unfortunately, the access modifiers on a class only affect visibility outside the assembly you're building. C++ doesn't support any sort of access modifiers that apply to namespaces in the way you're describing.
遗憾的是,类上的访问修饰符仅影响您正在构建的程序集之外的可见性。 C ++不支持以您描述的方式应用于命名空间的任何类型的访问修饰符。
A common idiom for simulating this is to put the "private" code into a detail
namespace (e.g. put it in MyNamespace::detail
). This is used a lot in e.g. the boost libraries. By convention, code in a detail namespace should only be used by code in the enclosing namespace (so MyNamespace::detail
should only be used by code in MyNamespace
), although the compiler won't enforce this for you.
模拟这个的常用习惯是将“私有”代码放入详细命名空间(例如将其放在MyNamespace :: detail中)。这在例如使用中很多。升级库。按照惯例,详细命名空间中的代码只能由封闭命名空间中的代码使用(因此MyNamespace :: detail应仅由MyNamespace中的代码使用),尽管编译器不会为您强制执行此操作。