포스트

[C++] 유효범위 Scope

[C++] 유효범위 Scope

C++ 유효 범위(Scope) 정리 및 상속 관계에서의 동작

C++에서 스코프(Scope, 유효 범위) 란 변수나 함수, 클래스 등이 언제 어디서까지 접근 가능한지를 결정하는 규칙 입니다. 스코프를 잘 이해하면 코드의 안정성, 가독성, 유지보수성 이 높아지고, 네이밍 충돌을 방지할 수 있습니다.


1. 스코프의 종류

1.1 블록 스코프 (Block Scope)

1
2
3
4
5
6
7
8
void func() {
    int a = 10;
    {
        int b = 20;
        // b 사용 가능
    }
    // b는 여기서 사용 불가
}
  • {} 중괄호 내부에서 선언된 변수는 해당 블록 안에서만 유효합니다.
  • 블록을 벗어나면 자동으로 소멸됩니다.

1.2 함수 스코프 (Function Scope)

  • 함수 내부에서 선언된 변수는 해당 함수 안에서만 유효합니다.
  • 다른 함수에서는 같은 이름을 재사용할 수 있습니다.
1
2
void f1() { int x = 1; }
void f2() { int x = 2; } // f1의 x와는 별개

1.3 전역 스코프 (Global Scope)

  • 함수 외부에서 선언된 변수는 프로그램 전체에서 접근할 수 있습니다.
1
2
int globalVar = 42;
void func() { std::cout << globalVar; }

1.4 클래스 스코프 (Class Scope)

  • 클래스 내부에서 정의된 멤버는 클래스 스코프를 갖습니다.
  • 클래스 외부에서 접근 시 범위 지정 연산자(::) 사용
1
2
3
4
5
6
7
8
9
class MyClass {
public:
    int value;
    void show();
};

void MyClass::show() {
    std::cout << value;
}

1.5 네임스페이스 스코프 (Namespace Scope)

1
2
3
4
namespace Math {
    int add(int a, int b) { return a + b; }
}
int x = Math::add(1, 2);

1.6 정적 스코프 (Static Scope)

  • static 변수는 선언된 스코프 내부에서만 접근 가능하지만, 프로그램 종료까지 메모리에 유지됩니다.
1
2
3
4
5
void counter() {
    static int count = 0;
    count++;
    std::cout << count;
}

2. 이름 숨김(Name Hiding)과 Shadowing

  • 내부 스코프에서 외부와 같은 이름을 가진 식별자를 정의하면 외부 이름은 숨겨짐
1
2
3
4
5
int x = 100;
void func() {
    int x = 50;  // 전역 x는 숨겨짐
    std::cout << x;  // 50
}
  • 전역 변수에 접근하려면 ::x를 사용

3. 상속 관계에서의 스코프 동작

3.1 부모 멤버에 접근하기

  • 자식 클래스는 부모 클래스의 public 및 protected 멤버에 접근 가능
  • 범위 지정 연산자(::)로 명확하게 접근 가능
1
2
3
4
5
6
7
8
class Base { public: int x = 10; };
class Derived : public Base {
public:
    void show() {
        std::cout << x;        // Base::x
        std::cout << Base::x;  // 명시적 접근
    }
};

3.2 이름 숨김 (Name Hiding)

  • 자식 클래스에서 동일한 이름을 정의하면 부모 클래스의 이름은 숨겨짐 (override 아님)
1
2
3
4
5
6
7
8
9
10
class Base {
public:
    int value = 100;
    void show() { std::cout << "Base\n"; }
};
class Derived : public Base {
public:
    int value = 200;
    void show(int x) { std::cout << "Derived: " << x << "\n"; }
};
  • 위 코드에서 Derived d; d.show();는 오류 (Base::show 숨겨짐)

3.3 using 선언으로 부모 멤버 노출

1
2
3
4
5
class Derived : public Base {
public:
    using Base::show;
    void show(int x) { std::cout << "Derived: " << x << "\n"; }
};

3.4 접근 제어자에 따른 상속 시 스코프

상속 방식Base의 public 멤버Base의 protected 멤버Base의 private 멤버
public 상속publicprotected접근 불가
protected 상속protectedprotected접근 불가
private 상속privateprivate접근 불가

4. 다중 상속에서의 스코프 충돌

1
2
3
4
5
6
7
8
9
class A { public: void f() { std::cout << "A\n"; } };
class B { public: void f() { std::cout << "B\n"; } };
class C : public A, public B {
public:
    void test() {
        A::f();  // 명시적으로 지정
        B::f();
    }
};

5. 스코프와 this 포인터

  • 상속 관계에서 this는 자신의 타입으로 해석됨
  • 필요 시 부모 포인터로 변환해 사용할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
class Base {
public:
    void print() { std::cout << "Base::print()\n"; }
};

class Derived : public Base {
public:
    void callBase() {
        Base* basePtr = this;
        basePtr->print();
    }
};

6. 요약

스코프 종류설명
블록 스코프{} 내부 유효
함수 스코프함수 내부 변수 범위
전역 스코프파일 전체 또는 프로그램 전역에서 접근 가능
클래스 스코프클래스 멤버 유효 범위
네임스페이스 스코프특정 네임스페이스 내부 범위
정적 스코프접근은 제한되지만 메모리는 유지됨
상속 스코프부모 멤버 상속 및 이름 숨김, 접근 제어자에 따라 다름

C++의 스코프는 단순한 변수 접근 범위를 넘어, 상속 관계, 다형성, 네임스페이스 등과 얽혀 복잡하게 동작할 수 있습니다. 이를 명확히 이해하는 것은 안정적인 객체지향 설계에 매우 중요합니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.