반응형

1. Namespace

namespace는 개발자가 코드의 부분을 명시적으로 이름을 붙여 나눠놓은 것이라고 보면 된다.

#include<iostream>

namespace A
{
	int number = 1234;
	void func()
	{
		std::cout << "func() from A" << std::endl;
	}
}

namespace B
{
	int number = 2345;
	void func()
	{
		std::cout << "func() from B" << std::endl;
	}
}

int main()
{
	std::cout << A::number << std::endl;
	A::func();
	std::cout << B::number << std::endl;
	B::func();
	return 0;
}

그림1. 실행결과.

위의 소스를 보면, 전역에 namespace A와 namespace B를 선언하여,

두 공간 안에 number라는 정수형 변수를 선언하고 값을 넣어준 것을 볼 수 있다.

또, func라는 함수를 선언해서 각각의 공간에 넣어주었다.

 

그리고 main 함수 안에서는 A::number, B::number와 같은 방법으로 각 공간 안의 변수에 접근하고 있는 것을 볼 수 있다. 두 변수는 이름이 같지만, 서로 다른 변수로 취급되는 것도 출력 결과를 통해 확인할 수 있다.

 

함수의 경우에도, A::func(), B::func()처럼, 이름은 같으나 서로 다른 함수라는 것을 namespace를 통해 나타내고 있다.


2. using 키워드

namespace로 공간을 명시적으로 만들어 나눌 수 있다는 것은 알겠는데,

사용할 때 명시적으로 공간의 이름을 앞에 붙여야 하기 때문에 불편하다. 생략해서 사용하는 방법은 없을까? 이는 using 키워드를 사용하면 가능하다.

#include<iostream>

namespace A
{
	int number = 1234;
	void func()
	{
		std::cout << "func() from A" << std::endl;
	}
}

using namespace A; // namespace A 사용!

int main()
{
	std::cout << number << std::endl; // 이 number는 A의 number
	func(); // 이 func()는 A의 func()
	return 0;
}

그림2. 실행결과.

 

using 키워드는 지정된 namespace 안의 내용을 모두 꺼내어 사용하게 해 준다고 보면 된다.

따라서 A라는 namespace에 using 키워드를 사용했으니,

이제 number와 func라고만 쓰면 당연히 A의 number와 func를 가져와 사용할 것이다.


3. Namespace의 모호성

using 키워드를 사용해서 공간의 이름을 생략하는 것도 좋지만, 너무 남용하는 것은 문제를 일으킬 수 있다. 다음 코드를 보자.

#include<iostream>

namespace A
{
	int number = 1234;
}

namespace B
{
	int number = 2345;
}

using namespace A; // namespace A 사용!
using namespace B; // namespace B 사용!

int main()
{
	std::cout << number << std::endl; // A? B?
	return 0;
}

namespace A와 namespace B 둘을 동시에 using으로 사용하고 있다.

이렇게 되면, 두 공간에 정의된 같은 이름의 number가 밖으로 나오게 되고, 컴파일러는 메인 함수에서 호출된 number가  두 공간 중에 어떤 number인지 알지 못하게 된다.

그림3. 에러

이런 경우에는 어떻게 해야 할까?

겹치는 경우에 대해 명시를 해주면 된다.

#include<iostream>

namespace A
{
	int number = 1234;
}

namespace B
{
	int number = 2345;
}

using namespace A; // namespace A 사용!
using namespace B; // namespace B 사용!

int main()
{
	std::cout << A::number << std::endl; // A!
	return 0;
}

그림4. 출력결과.

using을 썼더라도, 명시적으로 이름을 붙여줘서 공간을 구별할 수 있다.

위의 경우를 통해, using을 사용할 경우 각 namespace의 내용을 잘 숙지하고 사용해야 한다는 것을 알게 되었다.


4. namespace std

사실 namespace에 대해 공부하기 이전부터 우리는 namespace를 사용했다.

바로 std라는 namespace에서 cout과 cin, 그리고 endl을 사용했다. 이제 using을 배웠으니 std 역시 생략이 가능하다는 것을 알 수 있다.

#include<iostream>

using namespace std;

int main()
{
	cout << "C++ programming" << endl;
	return 0;
}

그림5. 출력결과.

위 코드를 보면 cout과 endl의 앞에 std::를 붙이지 않고 사용한 것을 알 수 있다.

 

하지만 많은 사람들이 되도록이면 using을 namespace에 사용하지 않는 것을 권장한다.

간단한 실습 수준의 단계에서는 코드가 짧고, 겹칠 문제가 없지만 남이 만든 라이브러리를 사용하거나, 협업을 한다거나, 아주 긴 코드를 작성하게 된다면, 3번에서 나온 경우처럼 충돌하는 일이 발생할 것이다.

 

따라서 간단한 실습용 코드에서만 using namespace을 사용하도록 하자. 또는, std안에 있는 내용과 자신의 코드가 겹치지 않게 일부만 가져와서 사용하도록 하자.

#include<iostream>

using std::cout; // cout만 사용
using std::endl; // endl만 사용

int main()
{
	cout << "C++ programming" << endl;
	return 0;
}

위 코드는 그림 5와 같은 출력 결과를 가진다.


읽을거리.

why is "using namespace std;" considered bad practice?

- using namespace std에 관한 질문이다.

std namespace에 한해서만 using 키워드를 쓰지 말라는 내용이 아니라,

모든 네임스페이스에 대해 using을 사용하는 습관을 들이지 말라는 내용이다.

반응형

'개념정리 > C++' 카테고리의 다른 글

6. Friend 키워드  (0) 2021.04.21
5. 참조자  (0) 2021.04.20
4. 동적할당과 소멸자  (0) 2021.04.19
3. 클래스  (0) 2021.04.18
1. 기본 자료형 및 입출력  (0) 2021.04.15
반응형

1. 기본 자료형

#include<iostream>

int main()
{
	bool b = true; // 새로생긴 자료형

	char c = 'c';
	int n = 10;
	long l = 320000000;
	long long ll = 23132165465849848;
	double lf = 3.1415926535;
	float f = 12.1f;

	return 0;
}

C에서 C++로 넘어오면서 bool이라는 자료형이 생겼다.

bool은 1바이트의 크기를 지니는 true와 false의 두 가지 상태를 저장할 수 있는 자료형이다.

그 외에 C에서 사용하던 자료형은 그대로 가져온 것을 알 수 있다.

 

또, 달라진 점이 있다면 기본 제공되는 헤더 파일을 불러올 때 .h를 붙이지 않는다는 것이다. 기존의 C에서 사용하던 헤더를 사용하고 싶으면 다음과 같이 쓸 수 있다.

#include<cstdio>
#include<cstring>

...

원래 쓰던 라이브러리 이름에 c만 붙여주면 된다.


2. string 클래스

#include<iostream>
#include<string>

int main()
{
	std::string str = "Hello, World!"; // 새로 생긴 문자열 클래스
	return 0;
}

bool 이외에 또 새로 생긴 것이 있는데, 바로 string 클래스이다.

C에서 문자열을 불편하게 포인터를 사용하여 처리했던 것과 다르게,

이제는 문자열을 기본적으로 제공하므로 편리하게 사용할 수 있다.


3. 기본 출력

#include<iostream>

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

그림1. 출력 결과.

위는 기본적인 c++의 출력방식이다.

변수의 경우의 출력도 한번 살펴보자.

#include<iostream>
#include<string>

int main()
{
	bool b = true;
	char c = 'c';
	int n = 10;
	long l = 320000000;
	long long ll = 23132165465849848;
	double lf = 3.1415926535;
	float f = 12.1f;
	std::string str = "A String";

	std::cout << b << std::endl << c << std::endl << n << std::endl << l;
	std::cout << ll;
	std::cout << std::endl;
	std::cout << lf << "\n" << f << '\n';
	std::cout << str << std::endl;
	return 0;
}

그림2. 출력 결과.

출력 결과를 보면 std::endl가 개행 문자와 같은 역할을 수행한다는 것을 알 수 있다.


4. 기본 입력

출력에 대해 알아보았으니 이제 입력받는 방법도 알아보자.

#include<iostream>

int main()
{
	int number;
	std::cin >> number;
	std::cout << "입력받은 정수: " << number << std::endl;
	return 0;
}

입력은 std::cin으로부터 가능하다. 이번에는 >>를 사용하여 뒤에 입력받고 싶은 변수명을 넣으면 된다.


읽을거리.

Why we should avoid using std::endl

- std::endl의 필요성에 대해 찾아보다가 찾은 글이다.

std::endl이 그냥 개행 문자를 출력하는 것보다 비 효율적이므로 과하게 사용하지 않는 것이 좋다는 글이다.

반응형

'개념정리 > C++' 카테고리의 다른 글

6. Friend 키워드  (0) 2021.04.21
5. 참조자  (0) 2021.04.20
4. 동적할당과 소멸자  (0) 2021.04.19
3. 클래스  (0) 2021.04.18
2. Namespace  (0) 2021.04.17

+ Recent posts