728x90
C++ 클래스를 사용 하다보면, 컴파일러가 은근슬쩍 만들어내는 함수가 4가지가 있다.
- 기본 생성자
- 복사 생성자
- 대입 연산자
- 소멸자
이것들이 보통의 경우 별로 신경 쓸 일이 없는데, 다음과 같은 상황에선 손을 좀 써 줘야 한다.
1. 기본 생성자 요구 (default)
- class NonCopyable
- {
- private:
- NonCopyable(const NonCopyable&);
- };
- int main()
- {
- // Compile error : C2512: 'NonCopyable' : 사용할 수 있는 적절한 기본 생성자가 없습니다.
- NonCopyable nc;
- }
기본 생성자는 기본 생성자가 아닌, 어떠한 생성자라도 존재할 경우 자동으로 생성되지 않는다.
(이것이 복사 생성자가 되었던, 인자를 가지는 다른 형태의 생성자이든 말이다).
따라서, 기본 생성자 형으로 객체를 생성하면, 사용할 수 있는 적절한 기본 생성자가 없다며 컴파일 에러가 발생한다.
이 경우, 아래와 같이 기본 생성자를 직접 선언/정의해 주어야 컴파일 에러가 발생하지 않는다.
- class NonCopyable
- {
- public:
- NonCopyable() {}
- private:
- NonCopyable(const NonCopyable&);
- };
- int main()
- {
- NonCopyable nc;
- }
이 경우 C++11에서는 아래와 같이 default 생성자를 선언만으로 해결할 수 있다.
- class NonCopyable
- {
- public:
- NonCopyable() = default;
- private:
- NonCopyable(const NonCopyable&);
- };
- int main()
- {
- NonCopyable nc;
- }
위 예제에서는 NonCopyable() 생성자의 default 생성을 명시적으로 요구하였으므로, 기본 생성자가 생성된다.
2. 복사, 대입 금지 클래스 (delete)
특정 클래스에 대해선 복사도 대입도 막고 싶은 경우 기존 C++ 0x 까진 아래와 같이 작성하였다.
- class NonCopyable
- {
- public:
- NonCopyable() {}
- ~NonCopyable() {}
- private:
- NonCopyable(const NonCopyable&);
- NonCopyable& operator = (const NonCopyable&);
- };
위 방식은 우선 복사 생성자와 대입 연산자를 private으로 두어 외부에서 접근 에러가 발생하게 하는 방식이고,
만약, 위 코드에서 복사 생성자와 대입 연산자의 접근 지정자를 public으로 두었다면,
선언만 하고 정의를 하지 않아 링크 에러가 나게 하는 식으로 사용을 금지시키는 방식이었다.
이를 C++11의 delete를 명시적으로 붙여주면, 이들에 대한 사용이 확실히 금지 된다.
- class NonCopyable
- {
- public:
- NonCopyable() {}
- ~NonCopyable() {}
- // 명시적으로 복사 생성자 / 대입 연산자가 disable 처리 되었음
- NonCopyable(const NonCopyable&) = delete;
- NonCopyable& operator = (const NonCopyable&) = delete;
- };
음 여기까지만 봤을 땐, 뭐 기존에 비해 크게 이득이 뭔가 싶겠지만,
delete의 경우 조금 더 요긴하게 사용할 수 있다.
delete 키워드는 아무 함수에나 사용할 수 있기 때문에,
멤버 함수의 파라미터에 대해 암시적인 형변환이 일어나는 것을 사전에 방지할 수 있다.
- // int 타입에 대해선 받지 않겠음.
- struct NoInt
- {
- void f(double i);
- void f(int) = delete;
- };
- // f의 인자로 double 형을 제외하고는 완전히 금지하겠다.
- // 즉, 컴파일러가 암시적으로 형 변환하는 것까지 완벽 차단.
- struct OnlyDouble
- {
- void f(double d);
- template<class T> void f(T) = delete;
- };
지금까지 default / delete 키워드에 대해 알아 보았지만, 아쉽게도 Visual Studio2013부터만 지원된다.
728x90
'Basic Programming > C++ 11' 카테고리의 다른 글
C++11 - final, override 키워드 (0) | 2017.09.18 |
---|---|
C++11 - std::thread (0) | 2016.12.02 |
C++11 - std::mutex (lock_guard, try_lock, try_lock_for, recursive_mutex) (0) | 2016.11.25 |
C++11 - nullptr (0) | 2016.02.26 |
C++11 - enum (0) | 2016.02.26 |