为了账号安全,请及时绑定邮箱和手机立即绑定

为什么要在C ++中使用嵌套类?

为什么要在C ++中使用嵌套类?

C++
波斯汪 2019-11-22 11:04:48
有人可以将我引向一些不错的资源来理解和使用嵌套类吗?我有一些像《编程原理》之类的材料,以及诸如《IBM Knowledge Center-Nested Classes》之类的东西但是我仍然很难理解他们的目的。有人可以帮我吗?
查看完整描述

3 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

嵌套类与常规类一样,但是:


它们具有附加的访问限制(就像类定义中的所有定义一样),

它们不会污染给定的名称空间,例如全局名称空间。如果您认为B类与A类之间的联系如此紧密,但是A和B的对象不一定相关联,那么您可能希望仅通过对A类进行范围界定来访问B类(将其称为A ::类)。

一些例子:


公开嵌套类以将其置于相关类的范围内

假设您想拥有一个SomeSpecificCollection将聚集class对象的类Element。然后,您可以:


声明两个类:SomeSpecificCollection和Element-不好,因为名称“ Element”足够通用,可能导致名称冲突


引入命名空间someSpecificCollection并声明类someSpecificCollection::Collection和someSpecificCollection::Element。没有名称冲突的风险,但是它还能变得更加冗长吗?


声明两个全局类SomeSpecificCollection和SomeSpecificCollectionElement-有一些小缺点,但可能还可以。


声明全局类SomeSpecificCollection和Element作为其嵌套类的类。然后:


您不会冒任何名称冲突的风险,因为Element不在全局名称空间中,

在实现中,SomeSpecificCollection您将just 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

};

然后一个将呼叫:


Product p(Product::FANCY, Product::BOX);

但是,在查看的代码完成建议时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

};

然后,调用看起来像:


Product p(Product::ProductType::FANCY, Product::ProductBoxType::BOX);

然后,通过输入Product::ProductType::IDE,只能从建议的范围中获取枚举。这也减少了犯错的风险。


当然,对于小型类而言,这可能不是必需的,但是如果一个类有很多枚举,那么对于客户端程序员来说,事情变得更容易了。


同样,如果需要,您可以在模板中“组织”一大堆typedef。有时这是一个有用的模式。


PIMPL成语

PIMPL(指向IMPLementation的指针的缩写)是一种惯用法,可用于从标头中删除类的实现细节。每当头的“实现”部分更改时,这都减少了根据类的头重新编译类的需求。


通常使用嵌套类来实现:


Xh:


class X {

public:

    X();

    virtual ~X();

    void publicInterface();

    void publicInterface2();

private:

    struct Impl;

    std::unique_ptr<Impl> impl;

}

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

如果完整的类定义需要某些外部库中类型的定义,该外部库具有沉重的或难看的头文件(使用WinAPI),则此功能特别有用。如果使用PIMPL,则只能将任何特定于WinAPI的功能封装在中,.cpp而永远不要将其包括在内.h。


查看完整回答
反对 回复 2019-11-22
  • 3 回答
  • 0 关注
  • 605 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信