C++에서 변수와 함수의 범위(scope)는 그들이 어디에서 선언되고, 어디에서 접근할 수 있는지를 결정하는 중요한 개념입니다. 이 코드 예제에서는 C++에서 다양한 범위를 활용하는 방법을 보여주며, 각 범위가 어떻게 작동하는지 설명합니다.
extern int x;
int y = 10;
int getX()
{
return x;
}
int getY()
{
return y;
}
extern int x;
: x
변수가 다른 파일에서 선언되어 있으며, 이 파일에서 사용할 것임을 알립니다. extern
키워드는 전역 변수를 다른 파일에서 참조할 수 있게 합니다.int y = 10;
: y
는 정적 전역 변수로 초기화됩니다. 이 변수는 전역 범위에서 접근 가능합니다.getX()
함수: x
의 값을 반환하는 함수입니다. x
는 외부 파일에서 정의됩니다.getY()
함수: y
의 값을 반환하는 함수입니다. 이 파일 내에서 정의된 전역 변수 y
를 사용합니다.#include <iostream>
using namespace std;
int x = 10;
int getX();
static int y = 10;
int getY();
int x = 10;
: 이 파일에서 x
변수가 정의됩니다. 이전에 extern int x;
로 선언되었으므로, 다른 파일에서 접근 가능합니다.static int y = 10;
: y
는 정적 변수로 정의되며, 이 파일 내에서만 접근할 수 있습니다. static
키워드는 변수의 파일 범위(file scope)를 설정하여, 다른 파일에서 접근할 수 없게 합니다.getX()
및 getY()
함수: 앞서 선언된 getX()
와 getY()
함수를 정의하며, 각각 x
와 y
값을 반환합니다.enum struct RequestType
{
Login, Register, Update, Delete
};
namespace CompanyA
{
int num;
}
namespace CompanyB
{
int num;
}
enum struct RequestType
: 이 열거형은 Login
, Register
, Update
, Delete
라는 네 가지 상태를 정의합니다. 이 열거형의 이름은 RequestType::Login
처럼 RequestType
범위 내에서 사용됩니다.namespace CompanyA
, namespace CompanyB
: 각각의 네임스페이스 안에 동일한 이름의 변수가 정의되어 있습니다. 네임스페이스는 이름 충돌을 방지하는 역할을 합니다. 예를 들어, CompanyA::num
과 CompanyB::num
은 서로 다른 변수를 가리킵니다.main
함수에서의 범위 사용 예제int main()
{
{
// Block scope
int a = 0;
cout << a << endl;
cout << &a << endl;
cout << endl;
{
static int a = 10; // 블록에 a가 선언되어 상단에서 선언된 a가 가렸음
cout << a << endl;
cout << &a << endl;
cout << endl;
}
cout << a << endl;
cout << &a << endl; // 최초로 선언 된 a, 블록 내부의 a가 static이기 때문에 해제가 된 것은 아님
cout << endl;
{}
로 감싸진 범위 안에서 변수 a
가 선언됩니다. 이 a
는 블록 내에서만 접근할 수 있습니다.static
으로 선언된 a
는 외부 블록의 a
를 가립니다. 이 static
변수는 프로그램이 종료될 때까지 유지되며, 동일한 블록에 다시 진입해도 이전 값이 유지됩니다.a
는 접근 가능하며, static
으로 선언된 내부 블록의 a
와는 다른 주소를 가집니다. if (int num = 1)
{
cout << num << endl;
}
//num = 1; 접근할 수 없음
if (int num = 0)
{
cout << num << endl;
}
else
{
cout << num << endl; // else에서는 접근할 수 있음
}
if
문 내에서 선언된 num
변수는 해당 조건문 블록에서만 유효합니다. else
블록에서도 접근할 수 있지만, if
블록 밖에서는 접근할 수 없습니다. 이는 블록 범위의 또 다른 예입니다. for (int i = 0; i < 10; ++i)
{
}
// i = 1; // 접근할 수 없음
for
문 내에서 선언된 i
변수도 해당 반복문 블록 내에서만 유효합니다. 반복문이 끝난 후 i
는 범위를 벗어나므로 접근할 수 없습니다. {
// Global scope
cout << getX() << endl;
x = 20;
cout << getX() << endl;
}
x
변수는 전역 범위에서 선언된 변수로, 프로그램의 모든 부분에서 접근 가능합니다. getX()
함수를 통해 x
값을 출력한 후, 값을 변경하여 다시 출력합니다. {
// File scope
cout << getY() << endl;
y = 20;
cout << getY() << endl; // 변하지 않음. 10 출력
}
y
변수는 static
으로 선언되어 파일 범위를 가집니다. 따라서 y
의 값을 변경해도, 이전에 선언된 정적 변수 y
는 영향을 받지 않고, 초기값인 10
이 유지됩니다. {
// Enumeration scope
RequestType::Login;
RequestType::Update;
RequestType::Register;
RequestType::Delete;
}
RequestType
열거형의 멤버는 RequestType::
이라는 범위 안에서 사용됩니다. 이는 열거형 멤버 이름이 전역적으로 사용되는 것을 방지합니다. {
// Namespace scope
// 이름 중복을 피하기 위해 사용.
// 예를 들어 전역 변수명의 중복을 피할 수 있다
CompanyA::num;
CompanyB::num;
// using namespace 를 사용하여 해당 namespace를 가져올 수 있음
// using std::cout, cout 만 현재 namespace로 가져옴
}
CompanyA
와 CompanyB
라는 서로 다른 네임스페이스에 같은 이름의 num
변수가 정의되어 있습니다. 네임스페이스는 이름 충돌을 방지하고, 코드의 모듈화를 지원합니다.using
키워드를 사용하면 특정 네임스페이스를 현재 범위로 가져올 수 있으며, 이로 인해 코드의 가독성이 향상됩니다. 예를 들어, std::cout
대신 cout
을 사용할 수 있습니다.전역 범위(Global scope): 프로그램 전체에서 접근 가능한 변수와 함수가 여기에 포함됩니다. 그러나 전역 변수를 너무 많이 사용하면, 코드의 복잡성과 의존성이 증가할 수 있습니다.
파일 범위(File scope): static
키워드를 사용하여 선언된 변수나 함수는 해당 파일 내에서만 접근 가능합니다. 이를 통해 다른 파일에서 동일한 이름의 변수가 존재하더라도 충돌을 피할 수 있습니다.
블록 범위(Block scope): {}
로 감싸인 블록 내에서만 유효한 변수들입니다. 이 범위는 프로그램의 흐름을 이해하고, 변수의 수명을 관리하는 데 중요합니다.
네임스페이스 범위(Namespace scope): 네임스페이스는 이름 충돌을 방지하고 코드의 모듈화를 지원합니다. 이를 통해 코드를 더욱 구조화하고 관리하기 쉽게 만듭니다.
열거형 범위(Enumeration scope): 열거형 멤버는 열거형 이름으로 구분되는 범위 안에서 사용됩니다. 이를 통해 전역적으로 중복될 수 있는 이름을 방지할 수 있습니다.