类可以定义在某个函数的内部,我们称这样的类为局部类(local class)。局部类定义的类型只在定义它的作用域内可见。和嵌套类不同,局部类的成员受到严格控制。局部类的所有成员(包括函数在内)都必须完整定义在类的内部。因此,局部类的作用与嵌套类相比相差很远。局部类只在函数内部有效,无法在函数外部调用。
在实际编程的过程中,因为局部类的成员必须完整定义在类的内部,所以成员函数的复杂性不可能太高。局部类的成员函数一般只有几行代码,否则我们就很难读懂它了。类似的,在局部类中也不允许声明静态数据成员,因为我们没法定义这样的成员。在局部类中,可以声明静态成员函数。
局部类不能使用函数作用域中的变量:局部类对其外层作用域中名字的访问权限收到很多限制,局部类只能访问外层作用域定义的类型名、静态变量以及枚举成员。如果局部类定义在某个函数内部,则该函数的普通局部变量不能被该局部类使用。
常规的访问保护规则对局部类同样适用:外层函数对局部类的私有成员没有任何访问特权。当然,局部类可以将外层函数声明为友元;或者更常见的情况是局部类将其成员声明成公有的。在程序中有权访问局部类的代码非常有限。局部类已经封装在函数作用域中,通过信息隐藏进一步封装就显得没什么必要了。
局部类中的名字查找:局部类内部的名字查找次序与其它类相似。在声明类的成员时,必须先确保用到的名字位于作用域中,然后再使用该名字。定义成员时用到的名字可以出现在类的任意位置。如果某个名字不是局部类的成员,则继续在外层函数作用域中查找;如果还没有找到,则在外层函数所在的作用域中查找。
嵌套的局部类:可以在局部类的内部再嵌套一个类。此时,嵌套类的定义可以出现在局部类之外。不过,嵌套类必须定义在与局部类相同的作用域中。局部类内的嵌套类也是一个局部类,必须遵循局部类的各种规定。嵌套类的所有成员都必须定义在嵌套类内部。
下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
#include "local_class.hpp"
#include <iostream>
#include <vector>
#include <algorithm>
namespace local_class_ {
// reference: C++ Primer(Fifth Edition) 19.7
int a{ 0 }, val{ 0 };
void foo(int val)
{
static int si;
enum Loc {a = 1024, b};
// Bar is local to foo
struct Bar {
Loc locVal; // ok: uses a local type name
int barVal;
void fooBar(Loc l = a) // ok: default argument si Loc::a
{
//barVal = val; // error: val is local to foo
barVal = ::local_class_::val; // ok: uses a global object
barVal = si; // ok: uses a static local object
locVal = b; // ok: use an enumerator
}
};
}
int test_local_class_1()
{
return 0;
}
////////////////////////////////////////////////
// reference: http://www.geeksforgeeks.org/local-class-in-c/
void fun()
{
class Test { // local to fun
public:
// Fine as the method is defined inside the local class
void method() {
std::cout << "Local Class method() called" << std::endl;
}
};
Test t;
t.method();
}
int test_local_class_2()
{
fun();
return 0;
}
/////////////////////////////////////////////////////
// reference: http://www.geeksforgeeks.org/local-class-in-c/
void fun2()
{
class Test { // local to fun
public:
static void method()
{
std::cout << "Local Class method() called"<<std::endl;
}
};
Test::method();
}
int test_local_class_3()
{
fun2();
return 0;
}
/////////////////////////////////////////////////////
// http://www.geeksforgeeks.org/local-class-in-c/
void fun3()
{
static int x = -3;
enum { i = 1, j = 2 };
// Local class
class Test {
public:
void method() {
std::cout << "x = " << x << std::endl; // fine as x is static
std::cout << "i = " << i << std::endl; // fine as i is enum
}
};
Test t;
t.method();
}
int test_local_class_4()
{
fun3();
return 0;
}
///////////////////////////////////////////////////////////
// http://www.geeksforgeeks.org/local-class-in-c/
int x = 11;
void fun4()
{
// First Local class
class Test1 {
public:
Test1() { std::cout << "Test1::Test1()" << std::endl; }
};
// Second Local class
class Test2 {
// Fine: A local class can use other local classes of same function
Test1 t1;
public:
void method() {
// Fine: Local class member methods can access global variables.
std::cout << "x = " << x << std::endl;
}
};
Test2 t;
t.method();
}
int test_local_class_5()
{
fun4();
return 0;
}
/////////////////////////////////////////////////////////
// reference: https://stackoverflow.com/questions/3235172/local-classes-in-c
int pqr()
{
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int test_local_class_6()
{
std::cout << "Return " << pqr() << std::endl;
return 0;
}
//////////////////////////////////////////////////////////
// reference: https://www.hscripts.com/tutorials/cpp/local-classes.php
int y;
void g()
{
class local {
public:
void put(int n) { ::local_class_::y = n; }
int get() { return ::local_class_::y; }
} ab;
ab.put(20);
std::cout << "The value assigned to y is::" << ab.get() << std::endl;
}
int test_local_class_7()
{
g();
return 0;
}
//////////////////////////////////////////////////////
// reference: http://en.cppreference.com/w/cpp/language/class
int test_local_class_8()
{
struct Local {
bool operator()(int n, int m) {
return n > m;
}
};
std::vector<int> v{ 1, 2, 3 };
std::sort(v.begin(), v.end(), Local()); // since C++11
for (int n : v) std::cout << n << ' ';
std::cout << std::endl;
return 0;
}
} // namespace local_class_
GitHub: https://github.com/fengbingchun/Messy_Test