C++ - 嵌套 类 有什么意义?
C++ - What's the point of nested classes?
我正在学习一些 C++,现在我正在反对它与 Java 的相似之处。我知道 Java 中内部 classes 的用途,但现在我试图在 C++ 中使用嵌套 classes, 我发现 的私有属性=15=] class 对嵌套的 class 不可见,那我为什么要使用它们呢?另外,有没有办法让这些属性可见?
它提供了另一种很好的封装技术。将一个 class 完全放在另一个 class 的 命名空间 中会降低它对代码库其他部分的可见性。这有助于实现可扩展性并减轻您的维护负担。
函数对象通常以这种方式编码。
I'm studying a little of C++ and now I'm fighting against it's similitudes with Java.
首先请注意,C++ 嵌套 class 与 Java 中的 static 嵌套 相似 127=]es。 C++ 语法中没有任何内容可以重现 Java 嵌套 classes.
I discover that private attributes of "container" class are not visible by inner class...
C++ 98
在 C++ 内部 classes 与 normal classes 没有区别,它们不是 class members 那么他们就不能访问容器 class' 的私有成员(不像其他语言,如 Java 或 C#)。
C++ 03
嵌套 classes 是 class 成员,但对他们可以访问的内容的限制仍然适用(另请参阅本答案末尾的 奇怪的事情 部分).它被认为是一个标准缺陷(参见 DR45),然后一些编译器更早地实现了 C++0x 访问规则,甚至在为 C++03 编译时(特别是 GCC,感谢 Jonathan Wakely 发现了这一点)。
C++ 11
此规则在 C++ 11 中更改,现在嵌套的 classes 可以访问容器 class 的私有成员。从 §11.7:
A nested class is a member and as such has the same access rights as any other member.
当然你仍然需要一个实例来访问非静态成员。
...so why I should use them?
然后它们是 实现 组相关 class 的细节,并且它们有相同的 问题 关于它们的用法您可能有其他语言版本(新手清楚,初级)。他们最大的好处 IMO 是封装,例如你有这个:
class stream {
virtual void write(const std::string text) = 0;
};
class channel {
public:
virtual stream* get_stream() = 0;
// Other methods...
};
class tcp_channel : public channel {
public:
virtual stream* get_stream() {
return new tcp_stream(this);
}
private:
class tcp_stream : public stream { /* implementation */ };
};
它们在某些情况下也有助于替换 嵌套命名空间:
class protocol {
public:
virtual void create_connection() = 0;
class tcp : public protocol { /* implementation */ };
class shared_memory : public protocol { /* implementation */ };
class named_pipes: public protocol { /* implementation */ };
};
auto media = protocol::tcp();
或隐藏实现细节:
class file_system_entry {
public:
class file : public file_system_entry { };
class directory : public file_system_entry { };
std::time_t get_last_modified() { ... }
void remove() { ... }
virtual void copy_to(std::string path) = 0;
private:
class local_handle {
// Implementation details
} _handle;
};
还有许多其他使用模式(另请参阅 Why would one use nested classes in C++? for a much better discussion), just remember not everyone will correctly understand (and use!) them. See also Pros and cons of using nested C++ classes and enumerations?
Also, is there a way to make visible those attributes?
在 C++ 11 之前你不能(当然除非你将它们声明为 friend
s 但请参阅下一段),如果你需要此功能只需使用 C++ 11 编译器(支持此功能)。 GCC 确实(很久以前)而且 MSVC 也有,我不知道其他编译器。
嵌套好友
C++ 11 访问规则和朋友 classes 之间有什么区别吗? 一般来说,它们 几乎等同 (自动 访问更简单):
class container {
public:
class nested;
friend class nested;
class nested { };
};
相比于:
class container {
public:
class nested { };
};
但是,对于前向声明,您会有一些副作用。还请记住,从可访问性的角度来看,它们是等价的(访问,如友谊,不能继承也不能传递)。这些示例无法编译:
class external : public container::nested {
public:
// No: only class declared inside "container"
// has access to private members, we do not inherit that
void foo(container obj) { /* access a private member of obj*/ }
};
// No, "container" has not access to "nested" private members,
// visibility isn't reciprocal
void container::foo(container::nested obj) {
// Access some private member of obj
}
// No, we don't have anything to do with container,
// visibility isn't transitive
void friendOfNested(container obj) {
// Access some private member of obj
}
那么完全等价吗? 否,因为 container
的朋友的私有成员在 nested
中是可访问的,如果它是 C++ 11 中的嵌套 class,但如果不是nested
是 container
的朋友。鉴于此概述结构:
class container;
class another {
friend class container;
};
class container {
public:
class nested { };
};
nested
可以访问 another
的私有成员:
void container::nested::foo(another obj) {
obj.somePrivateMember = 0;
}
之所以有效,是因为 nested
是 的 成员 container
,因此友谊的传递限制不适用。在 C++ 11 之前,将 nested
声明为 container
的友元,该代码将无法编译,因为友谊不可传递。
怪事
我们假设我们总是可以将嵌套的 class 声明为其容器的友元?其实标准说(SO/IEC14822:2003(E),11.8):
A friend of a class is a function or class that is not a member of the class...
那么我们不应该能够将nested
声明为container
的友元:在C++ 03中嵌套的class是class 成员(但标准明确表示他们无权访问容器私有对象,也不能成为容器 class 的好友)。似乎没有希望,幸运的是大多数编译器允许我们这样做(不管标准怎么说)。
不同就是不一样
Java 的 inner classes 创建假定与 outer[= 的对象相关联的对象17=] class,因此可以在不显式创建指针或引用的情况下从内部 class 的方法访问外部 class 的成员。 C++ 不这样做; nested class 只是一个 class,其定义嵌套在另一个 class 的定义中。这对于封装很方便,但仅此而已:它并不是要神奇地让该类型的对象知道包含类型的对象。
我正在学习一些 C++,现在我正在反对它与 Java 的相似之处。我知道 Java 中内部 classes 的用途,但现在我试图在 C++ 中使用嵌套 classes, 我发现 的私有属性=15=] class 对嵌套的 class 不可见,那我为什么要使用它们呢?另外,有没有办法让这些属性可见?
它提供了另一种很好的封装技术。将一个 class 完全放在另一个 class 的 命名空间 中会降低它对代码库其他部分的可见性。这有助于实现可扩展性并减轻您的维护负担。
函数对象通常以这种方式编码。
I'm studying a little of C++ and now I'm fighting against it's similitudes with Java.
首先请注意,C++ 嵌套 class 与 Java 中的 static 嵌套 相似 127=]es。 C++ 语法中没有任何内容可以重现 Java 嵌套 classes.
I discover that private attributes of "container" class are not visible by inner class...
C++ 98
在 C++ 内部 classes 与 normal classes 没有区别,它们不是 class members 那么他们就不能访问容器 class' 的私有成员(不像其他语言,如 Java 或 C#)。
C++ 03
嵌套 classes 是 class 成员,但对他们可以访问的内容的限制仍然适用(另请参阅本答案末尾的 奇怪的事情 部分).它被认为是一个标准缺陷(参见 DR45),然后一些编译器更早地实现了 C++0x 访问规则,甚至在为 C++03 编译时(特别是 GCC,感谢 Jonathan Wakely 发现了这一点)。
C++ 11
此规则在 C++ 11 中更改,现在嵌套的 classes 可以访问容器 class 的私有成员。从 §11.7:
A nested class is a member and as such has the same access rights as any other member.
当然你仍然需要一个实例来访问非静态成员。
...so why I should use them?
然后它们是 实现 组相关 class 的细节,并且它们有相同的 问题 关于它们的用法您可能有其他语言版本(新手清楚,初级)。他们最大的好处 IMO 是封装,例如你有这个:
class stream {
virtual void write(const std::string text) = 0;
};
class channel {
public:
virtual stream* get_stream() = 0;
// Other methods...
};
class tcp_channel : public channel {
public:
virtual stream* get_stream() {
return new tcp_stream(this);
}
private:
class tcp_stream : public stream { /* implementation */ };
};
它们在某些情况下也有助于替换 嵌套命名空间:
class protocol {
public:
virtual void create_connection() = 0;
class tcp : public protocol { /* implementation */ };
class shared_memory : public protocol { /* implementation */ };
class named_pipes: public protocol { /* implementation */ };
};
auto media = protocol::tcp();
或隐藏实现细节:
class file_system_entry {
public:
class file : public file_system_entry { };
class directory : public file_system_entry { };
std::time_t get_last_modified() { ... }
void remove() { ... }
virtual void copy_to(std::string path) = 0;
private:
class local_handle {
// Implementation details
} _handle;
};
还有许多其他使用模式(另请参阅 Why would one use nested classes in C++? for a much better discussion), just remember not everyone will correctly understand (and use!) them. See also Pros and cons of using nested C++ classes and enumerations?
Also, is there a way to make visible those attributes?
在 C++ 11 之前你不能(当然除非你将它们声明为 friend
s 但请参阅下一段),如果你需要此功能只需使用 C++ 11 编译器(支持此功能)。 GCC 确实(很久以前)而且 MSVC 也有,我不知道其他编译器。
嵌套好友
C++ 11 访问规则和朋友 classes 之间有什么区别吗? 一般来说,它们 几乎等同 (自动 访问更简单):
class container {
public:
class nested;
friend class nested;
class nested { };
};
相比于:
class container {
public:
class nested { };
};
但是,对于前向声明,您会有一些副作用。还请记住,从可访问性的角度来看,它们是等价的(访问,如友谊,不能继承也不能传递)。这些示例无法编译:
class external : public container::nested {
public:
// No: only class declared inside "container"
// has access to private members, we do not inherit that
void foo(container obj) { /* access a private member of obj*/ }
};
// No, "container" has not access to "nested" private members,
// visibility isn't reciprocal
void container::foo(container::nested obj) {
// Access some private member of obj
}
// No, we don't have anything to do with container,
// visibility isn't transitive
void friendOfNested(container obj) {
// Access some private member of obj
}
那么完全等价吗? 否,因为 container
的朋友的私有成员在 nested
中是可访问的,如果它是 C++ 11 中的嵌套 class,但如果不是nested
是 container
的朋友。鉴于此概述结构:
class container;
class another {
friend class container;
};
class container {
public:
class nested { };
};
nested
可以访问 another
的私有成员:
void container::nested::foo(another obj) {
obj.somePrivateMember = 0;
}
之所以有效,是因为 nested
是 的 成员 container
,因此友谊的传递限制不适用。在 C++ 11 之前,将 nested
声明为 container
的友元,该代码将无法编译,因为友谊不可传递。
怪事
我们假设我们总是可以将嵌套的 class 声明为其容器的友元?其实标准说(SO/IEC14822:2003(E),11.8):
A friend of a class is a function or class that is not a member of the class...
那么我们不应该能够将nested
声明为container
的友元:在C++ 03中嵌套的class是class 成员(但标准明确表示他们无权访问容器私有对象,也不能成为容器 class 的好友)。似乎没有希望,幸运的是大多数编译器允许我们这样做(不管标准怎么说)。
不同就是不一样
Java 的 inner classes 创建假定与 outer[= 的对象相关联的对象17=] class,因此可以在不显式创建指针或引用的情况下从内部 class 的方法访问外部 class 的成员。 C++ 不这样做; nested class 只是一个 class,其定义嵌套在另一个 class 的定义中。这对于封装很方便,但仅此而已:它并不是要神奇地让该类型的对象知道包含类型的对象。