C++

2024.02.28 - 키워드, 식별자, namespace, 범위 지정 연산자(::), std, using

강병곤 2024. 3. 2. 22:51
  • 키워드(keyword)

C++은 자체 사용을 위해 여러가지 특별한 의미를 가진 단어를 예약해놓았다. 이러한 단어를 키워드(keyword)라고 한다.

쉽게 말하면 int, float 같은 자료형 부터, if, while, for 등 편집기에서 다른 색으로 표시해주는 단어들을 키워드라고 할 수 있다. 

 

 

  • 식별자(identifier)

 C++에서 변수(variable), 함수(function), 타입(type) 또는 다른 종류의 객체(other kind of object)의 이름을 식별자라고 한다. 쉽게 말하자면, 변수명 같은 것을 식별자라고 한다. 식별자를 만들때는 따라야 하는 규칙이 있다.

- 키워드는 식별자가 될 수 없다.

- 식별자는 대소문자, 숫자, 문자로만 구성될 수 있다. (특수기호나 공백을 포함할 수 없다.)

- 식별자는 대소문자 또는 _문자로만 시작해야 한다. (숫자로 시작할 수 없다.)

- C++은 대문자와 소문자를 구별한다. 

 

 전에 배웠던 변수명을 짓는 규칙과 일맥상통한다. 함수명, 클래스명 같은 모든 식별자를 만들때 위와 같은 규칙을 따라야 한다. 

 

 

  • namespace
namespace 이름{
    선언내용;
};

 

 네임스페이스는 두 개 이상의 식별자가 같은 스코프(범위)에 있는 경우에 생기는 이름 충돌을 방지하기 위해서 사용한다. 쉽게 말하자면, 함수나 변수 등등의 이름이 중복되었을 때 에러가 생기지 않도록 영역을 지정해주는 역할을 한다. 여러 사람이 하나의 프로그램을 만들다 보면 서로 함수나 변수명이 같아지는 경우가 생길 수 있다. 네임스페이스로 이를 구분하면 에러를 막을 수 있을 뿐만 아니라, 코드의 구조가 명확해지고, 유지보수가 쉬워진다.

 

예시)

#include<iostream>

namespace ACompany {
    void Print() {
        std::cout << "나는 A회사의 Print()입니다." << std::endl;
    }
}
namespace BCompany {
    void Print() {
        std::cout << "나는 B회사의 Print()입니다." << std::endl;
    }
}
namespace CCompany {
    void Print() {
        std::cout << "나는 C회사의 Print()입니다." << std::endl;
    }
}
int main() {
    ACompany::Print();
    BCompany::Print();
    CCompany::Print();
}

 

모두 Print라는 이름의 함수이지만, 각 함수를 다른 네임스페이스로 구분해주었기 때문에 에러가 발생하지 않는다.

 

 

  • 범위 지정 연산자(scope resolution operator) ::
::식별자
클래스이름::식별자
네임스페이스::식별자
열거체::식별자 

 

 범위 지정 연산자(::)는 여러 범위에서 사용된 식별자(identifier)를 식별하고 구분하는데 사용하는 연산자이다. 이러한 식별자로는 변수, 함수 또는 열거체가 올 수 있다. 쉽게 말하면, 식별자(변수, 함수 등)가 어느 범위(클래스, 네임스페이스 등)에 있는지 구분해준다.

 

- ::식별자

#include<iostream>

int a = 10;
int main() {
	int a = 20;
	std::cout << ::a << std::endl;
	std::cout << a << std::endl;
}

 

식별자 앞에 아무 범위를 명시하지 않고 범위 지정 연산자(::)를 사용하면 글로벌 네임스페이스를 가리킨다. (글로벌 네임스페이스에는 이름이 없다.) ::a는 main()함수 안에 있는 지역변수 a(=20)를 가리키는 것이 아니라, 전역변수 a(=10)을 가리킨다. 

 

- 네임스페이스::식별자

#include<iostream>

namespace ACompany {
    void Print() {
        std::cout << "나는 ACompany 네임스페이스의 Print()" << std::endl;
    }
}
namespace BCompany {
    void Print() {
        std::cout << "나는 BCompany 네임스페이스의 Print()" << std::endl;
    }
}
int main() {
    ACompany::Print();
    BCompany::Print();
}

 

 

  • std

범위 지정 연산자를 공부하다 보니, 처음 출력하는 방법을 배웠을 때가 생각이 난다.

#include<iostream>

int main() {
	std::cout << "Hello World!" << std::endl;
}

출력을 하기 위해 썼던 코드 std::cout도 범위 지정 연산자를 사용해 범위(std)안의 함수(cout)를 불러오는 것임을 알게 되었다. C++은 표준 라이브러리의 모든 기능을 std라는 namespace의 영역에 옮겨놓았다. std는 standard(표준)의 약자이다.

 

 

  • using
using namespace 네임스페이스이름;

 

네임스페이스 안의 기능을 여러번 사용해야 하는 경우, 일일히 범위 지정 연산자(::)를 사용해 어떤 영역에서 왔는지 표시해주어야 하는 번거로움이 있다. using을 사용하면 단순하게 코드를 짤 수 있다.

 

- using 선언문 (The using declaration)

#include<iostream>

namespace ACompany {
    void Print() {
        std::cout << "나는 A회사의 Print()입니다." << std::endl;
    }
}
namespace BCompany {
    void Print() {
        std::cout << "나는 B회사의 Print()입니다." << std::endl;
    }
}

int main() {
    using ACompany::Print;

    Print();
}

using을 사용하는 첫번째 방법은 using 선언문이다. using ACompany::Print; 라고 쓰면 Print를 쓸때 마다 ACompany의 Print를 쓸 것임을 컴파일러에게 알려줄 수 있다. 다른 namespace의 Print와 충돌하는 경우, ACompany::Print가 사용된다. 

 

 

- using 지시문 (The using directive)

#include<iostream>

namespace ACompany {
    void Print() {
        std::cout << "나는 A회사의 Print()입니다." << std::endl;
    }
    void Print2() {
        std::cout << "Print2" << std::endl;
    }
}
namespace BCompany {
    void Print() {
        std::cout << "나는 B회사의 Print()입니다." << std::endl;
    }
}

int main() {
    using namespace ACompany;
 
    Print();
    Print2();
}

 

using을 사용하는 다른 방법은 using 지시문이다. using namspace ACompany; 라고 쓰면 ACompany 네임스페이스의 모든 것을 사용하고 싶다고 컴파일러에게 말한다. 컴파일러가 인식하지 못하는 이름을 찾으면 ACompany 네임스페이스를 검사한다. 

 

#include<iostream>

namespace ACompany {
    void Print() {
        std::cout << "나는 A회사의 Print()입니다." << std::endl;
    }
}
namespace BCompany {
    void Print() {
        std::cout << "나는 B회사의 Print()입니다." << std::endl;
    }
}

int main() {
    using namespace ACompany;
    using namespace BCompany;

    Print();
}

 

그러나 using 지시문을 사용하면 위와 같이 어떤 네임스페이스의 함수를 찾는 건지 모호해질 수 있다. using namespace std;를 사용하는 것도 사용자가 std안의 함수와 같은 이름의 함수를 만든 경우 충돌이 일어날 수 있다.