zen*_*gal 180 c++ nested inner-classes
有人可以指点我一些很好的资源来理解和使用嵌套类吗?我有一些材料,如编程原理和类似IBM知识中心 - 嵌套类的东西
但我仍然无法理解他们的目的.有人可以帮帮我吗?
Mar*_*ork 215
嵌套类很容易隐藏实现细节.
列表:
class List
{
public:
List(): head(nullptr), tail(nullptr) {}
private:
class Node
{
public:
int data;
Node* next;
Node* prev;
};
private:
Node* head;
Node* tail;
};
Run Code Online (Sandbox Code Playgroud)
在这里,我不想暴露Node,因为其他人可能决定使用该类,这会阻碍我更新我的类,因为暴露的任何东西都是公共API的一部分,必须永远维护.通过使类私有,我不仅隐藏了实现,我也说这是我的,我可能随时更改它,所以你不能使用它.
看看std::list
或者std::map
它们都包含隐藏的类(或者它们是什么?).重点是它们可能会也可能不会,但是因为实现是私有的并且隐藏了STL的构建者能够在不影响您使用代码的方式的情况下更新代码,或者因为需要而在STL周围留下大量旧行李保持与某些傻瓜的向后兼容性,他们决定使用隐藏在其中的Node类list
.
Kos*_*Kos 138
嵌套类就像常规类一样,但是:
一些例子:
假设您想要一个SomeSpecificCollection
可以聚合类对象的类Element
.然后你可以:
声明两个类:SomeSpecificCollection
和Element
- 坏,因为名称"元素"足够通用,以便导致可能的名称冲突
引入命名空间someSpecificCollection
并声明类someSpecificCollection::Collection
和someSpecificCollection::Element
.没有名字冲突的风险,但是它会变得更加冗长吗?
声明两个全局类SomeSpecificCollection
和SomeSpecificCollectionElement
-其中有轻微的缺陷,但可能确定.
将全局类SomeSpecificCollection
和类声明Element
为其嵌套类.然后:
SomeSpecificCollection
你的实现中,你只需要Element
和其他地方一样SomeSpecificCollection::Element
- 看起来+ - 与3.相同,但更清楚SomeSpecificCollection
也是一个类.在我看来,最后一个版本绝对是最直观的,因此也是最好的设计.
让我强调一下 - 这与制作两个名字更详细的全局类没有太大区别.它只是一个小小的细节,但它使代码更清晰.
这对于引入typedef或枚举特别有用.我将在这里发布一个代码示例:
class Product {
public:
enum ProductType {
FANCY, AWESOME, USEFUL
};
enum ProductBoxType {
BOX, BAG, CRATE
};
Product(ProductType t, ProductBoxType b, String name);
// the rest of the class: fields, methods
};
Run Code Online (Sandbox Code Playgroud)
然后会打电话给:
Product p(Product::FANCY, Product::BOX);
Run Code Online (Sandbox Code Playgroud)
但是当查看代码完成提议时Product::
,通常会列出所有可能的枚举值(BOX,FANCY,CRATE)并且很容易在这里犯一个错误(C++ 0x的强类型枚举有点解决这个问题,但没关系).
但是如果你使用嵌套类为这些枚举引入额外的范围,事情可能如下所示:
class Product {
public:
struct ProductType {
enum Enum { FANCY, AWESOME, USEFUL };
};
struct ProductBoxType {
enum Enum { BOX, BAG, CRATE };
};
Product(ProductType::Enum t, ProductBoxType::Enum b, String name);
// the rest of the class: fields, methods
};
Run Code Online (Sandbox Code Playgroud)
然后电话看起来像:
Product p(Product::ProductType::FANCY, Product::ProductBoxType::BOX);
Run Code Online (Sandbox Code Playgroud)
然后通过键入Product::ProductType::
IDE,只能获得建议的所需范围的枚举.这也降低了犯错的风险.
当然,对于小类来说可能不需要这样,但是如果有很多枚举,那么它会让客户端程序员更容易.
同样,如果您有需要,可以在模板中"组织"一大堆typedef.有时它是一种有用的模式.
PIMPL(指向IMPLementation的指针的缩写)是一个习惯用法,用于从头中删除类的实现细节.每当标题的"实现"部分发生变化时,这就减少了重新编译类的需要,具体取决于类的标题.
它通常使用嵌套类实现:
XH:
class X {
public:
X();
virtual ~X();
void publicInterface();
void publicInterface2();
private:
struct Impl;
std::unique_ptr<Impl> impl;
}
Run Code Online (Sandbox Code Playgroud)
X.cpp:
#include "X.h"
#include <windows.h>
struct X::Impl {
HWND hWnd; // this field is a part of the class, but no need to include windows.h in header
// all private fields, methods go here
void privateMethod(HWND wnd);
void privateMethod();
};
X::X() : impl(new Impl()) {
// ...
}
// and the rest of definitions go here
Run Code Online (Sandbox Code Playgroud)
如果完整的类定义需要来自某个外部库的类型定义,而这个外部库具有繁重或丑陋的头文件(使用WinAPI),这将特别有用.如果使用PIMPL,则只能包含任何特定于WinAPI的功能,.cpp
并且永远不会包含它.h
.
Joh*_*ing 21
我不太多使用嵌套类,但我偶尔会使用它们.特别是当我定义某种数据类型时,我想要定义一个为该数据类型设计的STL仿函数.
例如,考虑Field
具有ID号,类型代码和字段名称的泛型类.如果我想通过ID号或名称搜索vector
这些Field
s,我可能会构造一个仿函数来:
class Field
{
public:
unsigned id_;
string name_;
unsigned type_;
class match : public std::unary_function<bool, Field>
{
public:
match(const string& name) : name_(name), has_name_(true) {};
match(unsigned id) : id_(id), has_id_(true) {};
bool operator()(const Field& rhs) const
{
bool ret = true;
if( ret && has_id_ ) ret = id_ == rhs.id_;
if( ret && has_name_ ) ret = name_ == rhs.name_;
return ret;
};
private:
unsigned id_;
bool has_id_;
string name_;
bool has_name_;
};
};
Run Code Online (Sandbox Code Playgroud)
然后需要搜索这些Field
s的代码可以match
在Field
类本身中使用作用域:
vector<Field>::const_iterator it = find_if(fields.begin(), fields.end(), Field::match("FieldName"));
Run Code Online (Sandbox Code Playgroud)
Yeo*_*Yeo 13
可以使用嵌套类实现Builder模式.特别是在C++中,我个人认为它在语义上更清晰.例如:
class Product{
public:
class Builder;
}
class Product::Builder {
// Builder Implementation
}
Run Code Online (Sandbox Code Playgroud)
而不是:
class Product {}
class ProductBuilder {}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
167397 次 |
最近记录: |