当前位置: 首页 > 编程笔记 >

C++ 嵌套类/结构

沈俊晤
2023-03-14
本文向大家介绍C++ 嵌套类/结构,包括了C++ 嵌套类/结构的使用技巧和注意事项,需要的朋友参考一下

示例

甲class或struct还可以包含另一个class/struct内部本身的定义,这被称为“嵌套类”; 在这种情况下,包含类称为“封闭类”。嵌套类定义被认为是封闭类的成员,但在其他方面则是单独的。

struct Outer {
    struct Inner { };
};

从封闭类的外部,可以使用范围运算符访问嵌套类。但是,在封闭类的内部,可以使用没有限定符的嵌套类:

struct Outer {
    struct Inner { };

    Inner in;
};

// ...

Outer o;
Outer::Inner i = o.in;

与非嵌套class/一样struct,成员函数和静态变量可以在嵌套类内或在封闭的名称空间中定义。但是,由于它们被认为是与嵌套类不同的类,因此无法在封闭类中定义它们。

// 坏。
struct Outer {
    struct Inner {
        void do_something();
    };

    void Inner::do_something() {}
};


// 好。
struct Outer {
    struct Inner {
        void do_something();
    };

};

void Outer::Inner::do_something() {}

与非嵌套类一样,嵌套类可以在以后直接声明和定义,前提是在直接使用之前对其进行了定义。

class Outer {
    class Inner1;
    class Inner2;

    class Inner1 {};

    Inner1 in1;
    Inner2* in2p;

  public:
    Outer();
    ~Outer();
};

class Outer::Inner2 {};

Outer::Outer() : in1(Inner1()), in2p(new Inner2) {}
Outer::~Outer() {
    if (in2p) { delete in2p; }
}

C ++ 11

在C ++ 11之前,嵌套类只能static从封闭的类中访问类型名称,成员和枚举数。封闭类中定义的所有其他成员是禁止进入的。

json="[{"Type":"GreaterThanOrEqual","GroupName":null,"VersionName":"C++11"}]"> C ++ 11

从C ++ 11开始,嵌套类及其成员被视为friend封闭类的成员,并且可以根据通常的访问规则来访问其所有成员。如果嵌套类的成员需要能够评估封闭类的一个或多个非静态成员,则必须为它们传递一个实例:

class Outer {
    struct Inner {
        int get_sizeof_x() {
            return sizeof(x); // 合法(C ++ 11):x未评估,因此不需要实例。
        }

        int get_x() {
            return x; // 非法:没有实例就无法访问非静态成员。
        }

        int get_x(Outer& o) {
            return o.x; // 合法(C ++ 11):作为Outer的成员,Inner可以访问私有成员。
        }
    };

    int x;
};

相反,封闭类不会被视为嵌套类的朋友,因此,如果未明确授予其权限,则无法访问其私有成员。

class Outer {
    class Inner {
        // 朋友班外

        int x;
    };

    Inner in;

  public:
    int get_x() {
        return in.x; // 错误:int Outer :: Inner :: x是私有的。
        // Uncomment "friend" line above to fix.
    }
};

嵌套类的朋友不会自动视为封闭类的朋友;如果他们也需要成为封闭类的朋友,则必须分别声明。相反,由于封闭类不会自动被视为嵌套类的朋友,因此封闭类的朋友也不会被视为嵌套类的朋友。

class Outer {
    friend void barge_out(Outer& out, Inner& in);

    class Inner {
        friend void barge_in(Outer& out, Inner& in);

        int i;
    };

    int o;
};

void barge_in(Outer& out, Outer::Inner& in) {
    int i = in.i;  // 好。
    int o = out.o; // 错误:int Outer :: o是私有的。
}

void barge_out(Outer& out, Outer::Inner& in) {
    int i = in.i;  // 错误:int Outer :: Inner :: i是私有的。
    int o = out.o; // 好。
}

与所有其他类成员一样,嵌套类只有在具有公共访问权限的情况下才能从类外部进行命名。但是,只要您未明确命名它们,都可以访问它们,而不论访问修饰符是什么。

class Outer {
    struct Inner {
        void func() { std::cout << "I have no private taboo.\n"; }
    };

  public:
    static Inner make_Inner() { return Inner(); }
};

// ...

Outer::Inner oi; // 错误:外部::内部是私有的。

auto oi = Outer::make_Inner(); // 好。
oi.func();                     // 好。
Outer::make_Inner().func();    // 好。

您也可以为嵌套类创建类型别名。如果封闭类中包含类型别名,则嵌套类型和类型别名可以具有不同的访问修饰符。如果类型别名在封闭类的外部,则它要求嵌套类typedef或其嵌套类是公共的。

class Outer {
    class Inner_ {};

  public:
    typedef Inner_ Inner;
};

typedef Outer::Inner  ImOut; // 好。
typedef Outer::Inner_ ImBad; // 错误。

// ...

Outer::Inner  oi; // 好。
Outer::Inner_ oi; // 错误。
ImOut         oi; // 好。

与其他类一样,嵌套类既可以从其他类派生也可以从其他类派生。

struct Base {};

struct Outer {
    struct Inner : Base {};
};

struct Derived : Outer::Inner {};

通过允许程序员根据需要更新嵌套的类,这在封闭类是从另一个类派生的情况下很有用。可以与typedef结合使用,以为每个封闭类的嵌套类提供一致的名称:

class BaseOuter {
    struct BaseInner_ {
        virtual void do_something() {}
        virtual void do_something_else();
    } b_in;

  public:
    typedef BaseInner_ Inner;

    virtual ~BaseOuter() = default;

    virtual Inner& getInner() { return b_in; }
};

void BaseOuter::BaseInner_::do_something_else() {}

// ---

class DerivedOuter : public BaseOuter {
    //注意使用合格的typedef;BaseOuter :: BaseInner_是私有的。
    struct DerivedInner_ : BaseOuter::Inner {
        void do_something() override {}
        void do_something_else() override;
    } d_in;

  public:
    typedef DerivedInner_ Inner;

    BaseOuter::Inner& getInner() override { return d_in; }
};

void DerivedOuter::DerivedInner_::do_something_else() {}

// ...

// 调用BaseOuter :: BaseInner _ :: do_something();
BaseOuter* b = new BaseOuter;
BaseOuter::Inner& bin = b->getInner();
bin.do_something();
b->getInner().do_something();

// 调用DerivedOuter :: DerivedInner _ :: do_something();
BaseOuter* d = new DerivedOuter;
BaseOuter::Inner& din = d->getInner();
din.do_something();
d->getInner().do_something();

在上述情况下,BaseOuter和分别DerivedOuter提供成员类型InnerasBaseInner_和DerivedInner_。这允许在不破坏封闭类的接口的情况下派生嵌套类型,并允许嵌套类型被多态使用。

 类似资料:
  • 目标 了解如何定义嵌套类和何时适合使用它们 了解使用嵌套类的副作用 了解 new 运算符在嵌套类中的特殊用法 了解如何和何时使用静态内部类和匿名内部类 在何处使用嵌套类 顾名思义,嵌套类(或内部类) 是在一个类中定义的另一个类。 public class EnclosingClass { . . . public class NestedClass { . . . } } 像成

  • 要想实现一些复杂的功能,依靠简单的分支结构和多重分支结构等等是远远不够的。所以我们还需要分支嵌套结构。 1. 分支嵌套结构的语法 if (条件 1) { if (条件 2) { 执行语句 1 } else { 执行语句 2 } } else { if (条件 3) { 执行语句 3

  • 4. 嵌套结构体 结构体也是一种递归定义:结构体的成员具有某种数据类型,而结构体本身也是一种数据类型。换句话说,结构体的成员可以是另一个结构体,即结构体可以嵌套定义。例如我们在复数的基础上定义复平面上的线段: struct segment { struct complex_struct start; struct complex_struct end; }; 从第 1 节 “复合类型与结构体”

  • C++ 循环 一个循环内可以嵌套另一个循环。C++ 允许至少 256 个嵌套层次。 语法 C++ 中 嵌套 for 循环 语句的语法:for ( init; condition; increment ) { for ( init; condition; increment ) { statement(s); } statement(s); // 可以放置更多的语句 } C++ 中 嵌套 while

  • 问题内容: 我可以做以下事情吗? 问题答案: 香草CSS不可能。但是,您可以使用类似: Sass使CSS再次变得有趣。Sass是CSS3的扩展,添加了嵌套规则,变量,mixins,选择器继承等。使用命令行工具或网络框架插件将其转换为格式良好的标准CSS。 要么 不用构造长的选择器名称来指定继承,在Less中,您可以简单地将选择器嵌套在其他选择器中。这样可以使继承更清晰,样式表更短。 例:

  • 本页包含内容: 嵌套类型实例 嵌套类型的引用 枚举类型常被用于实现特定类或结构体的功能。也能够在有多种变量类型的环境中,方便地定义通用类或结构体来使用,为了实现这种功能,Swift允许你定义嵌套类型,可以在枚举类型、类和结构体中定义支持嵌套的类型。 要在一个类型中嵌套另一个类型,将需要嵌套的类型的定义写在被嵌套类型的区域{}内,而且可以根据需要定义多级嵌套。 嵌套类型实例 下面这个例子定义了一个结