内部类和匿名类
- 前言
- 一、内部类的概念
- 示例
- 二、内部类的特性
- 三、匿名类的概念
- 示例
- 四、匿名类的特性
- 总结
前言
内部类是定义在另一个类内部的类,它可以访问外部类的私有成员。匿名类是没有名字的类,通常用于一次性使用的简单对象创建,可以直接在需要使用的地方定义,并传递给其他方法。内部类和匿名类都是C++等编程语言的重要特性,它们可以简化代码结构,提高代码重用性。
一、内部类的概念
ps:可以安装友元类的定义来理解C++从入门到精通——友元
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。但是它可以访问外部类的私有成员,因为它被视为外部类的成员。内部类可以使用外部类的对象直接访问外部类的成员。内部类的定义可以在外部类的定义中或者在外部类的方法中,也可以在外部类的作用域之外定义。
内部类可以有自己的成员变量和成员函数,外部类可以使用内部类的对象访问内部类的成员。内部类的对象必须由外部类的对象来创建。
内部类可以在外部类的成员函数中访问外部类的私有成员,这样可以方便地实现封装和隐藏的特性。内部类还可以用于实现回调函数和迭代器等功能。
使用内部类可以提高代码的可读性和可维护性,因为内部类通常只在外部类中使用。此外,内部类还可以隐藏实现细节,提高代码的安全性。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
示例
以下是一个使用内部类的C++示例:
#include <iostream>
class OuterClass {
private:
int outerData;
public:
class InnerClass {
public:
void displayData(OuterClass& outer) {
std::cout << "Outer data: " << outer.outerData << std::endl;
}
};
void setOuterData(int data) {
outerData = data;
}
void useInnerClass() {
InnerClass inner;
inner.displayData(*this);
}
};
int main() {
OuterClass outer;
outer.setOuterData(10);
outer.useInnerClass();
return 0;
}
在上面的示例中,我们定义了一个包含内部类的外部类OuterClass
。OuterClass
拥有一个私有成员变量outerData
。内部类InnerClass
可以访问外部类的私有成员。
在OuterClass
的方法useInnerClass()
中,我们创建一个InnerClass
的实例inner
,然后调用inner
的方法displayData()
,该方法接受OuterClass
的引用作为参数并显示外部类的数据。
在main()
函数中,我们创建一个外部类的实例outer
,然后调用setOuterData()
来设置外部类的数据为10。接下来,我们调用useInnerClass()
来使用内部类,并且输出外部类的数据。
运行上述代码将输出:
Outer data: 10
这个示例展示了内部类如何访问外部类的私有成员,并且如何使用内部类作为外部类的一部分来实现更清晰和封装的代码结构。
二、内部类的特性
特性:
- 内部类可以定义在外部类的
public
、protected
、private
都是可以的。 - 注意内部类可以直接访问外部类中的
static
成员,不需要外部类的对象/类名。 sizeof(外部类)=外部类
,和内部类没有任何关系。
class A
{
private:
static int k;
int h;
public:
class B // B天生就是A的友元
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
};
};
int A::k = 1;
int main()
{
A::B b;
b.foo(A());
return 0;
}
三、匿名类的概念
在 C++ 中,匿名类是一种没有命名的局部类,它与匿名类似,但在 C++ 中有一些区别。匿名类是在声明的同时进行实例化的,它可以作为对象在堆栈上分配并使用,也可以作为类成员使用。与匿名类不同,C++ 的匿名类可以定义自己的方法和成员变量。
匿名类的声明和实例化通常在代码块内部完成,使用的语法类似于在堆栈上创建对象。匿名类的定义和实例化通常在花括号内,与代码块的语法类似。
示例
下面是一个定义和使用匿名类的示例:
#include <iostream>
int main() {
int num = 5;
// 定义并实例化一个匿名类
auto obj = [num]() {
// 匿名类的成员变量
int value = num;
// 匿名类的成员方法
void printValue() {
std::cout << "Value: " << value << std::endl;
}
// 返回匿名类对象
return *this;
}();
// 调用匿名类的成员方法
obj.printValue();
return 0;
}
在上面的示例中,我们使用 Lambda
表达式创建了一个匿名类,并在实例化时将 num
变量作为成员变量。然后,我们通过调用匿名类的成员方法来打印成员变量的值。
需要注意的是,C++ 中的匿名类只能在实例化时使用,无法在其他地方引用或复用。此外,匿名类的作用域仅限于声明它的代码块,超出该范围后将无法再使用。
四、匿名类的特性
C++匿名类具有以下特性:
-
没有类名:匿名类在声明时不需要提供类名,因此无法在其他地方引用或复用。它的作用域仅限于声明它的代码块。
-
可以定义成员变量和成员方法:在匿名类内部,可以定义自己的成员变量和成员方法。这些成员变量和成员方法仅在匿名类内部可见。
-
可以实例化为对象:匿名类可以在声明时进行实例化,就像在堆栈上创建一个对象一样。实例化后,可以使用该对象调用匿名类的成员方法或访问成员变量。
-
可以接受初始化参数:匿名类可以接受初始化参数,在实例化时传递给构造函数。可以使用
Lambda
表达式来定义匿名类,并在Lambda
表达式内部使用捕获列表来传递初始化参数。 -
作用域限制:匿名类的作用域仅限于声明它的代码块。超出该范围后,无法再使用匿名类。
-
简化代码结构:匿名类可以用于简化代码结构,并提供一种在特定上下文中定义和使用临时类的方式。它可以用于一些需要局部定义的简单类情况,而无需单独为其创建一个命名类。
尽管匿名类具有一定的灵活性和便利性,但由于它的作用域和无法重用的特性,通常情况下更推荐使用命名类来组织和管理代码。匿名类更适用于一些临时、简单的特定场景下。
总结
- 生命周期即在当前作用域下,即用即销毁
- 通过匿名对象可以简化代码