일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- virtual function
- effective modern c++
- Smart Pointer
- reference
- more effective c++
- resource management class
- 언리얼
- 메타테이블
- Effective c++
- 비교 함수 객체
- 상속
- 반복자
- 오블완
- 스마트 포인터
- iterator
- operator new
- c++
- exception
- 영화
- 암시적 변환
- implicit conversion
- 함수 객체
- UE4
- 예외
- 참조자
- lua
- effective stl
- 영화 리뷰
- 티스토리챌린지
- 게임
Archives
- Today
- Total
스토리텔링 개발자
[Effective Modern C++] 11. 삭제된 함수(deleted function) 본문
Effective C++/Effective Modern C++
[Effective Modern C++] 11. 삭제된 함수(deleted function)
김디트 2025. 2. 19. 10:45728x90
항목 11. 정의되지 않은 private 함수보다 삭제된 함수를 선호하라
코드의 특정 함수를 호출하지 못하도록 하기
- 그냥 그 함수를 선언하지 않는다.
- 특수 멤버 함수들에서는 그게 쉽지 않다.
- 즉, C++이 필요에 따라 자동으로 작성하는 멤버 함수들.
- 예를 들면 복사 생성자, 복사 대입 연산자.
- C++98에서의 접근 방식
- 해당 함수들을 private 선언하고 정의하지 않는다.
- private에 선언되어 있으므로 호출할 수 없다.
- 정의하지 않았으므로 호출 시 링크 실패한다.
- C++98 표준 입출력 스트림 객체는 복사를 방지하도록 구현되어 있다.
template<class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base
{
public:
...
private:
basic_ios(const basic_ios&); // not defined
basic_ios& operator=(const basic_ios&); // not defined
};
- C++11에서의 접근 방식
- 해당 함수들의 선언 끝에 "= delete"를 붙인다.
template<class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base
{
public:
...
basic_ios(const basic_ios&) = delete;
basic_ios& operator=(const basic_ios&) = delete;
...
};
함수 private 선언과 함수 delete의 차이
- 삭제된 함수는 어떤 방법으로든 사용할 수 없다.
- 즉, 컴파일이 실패한다.
- C++98 방식은 링크 시점에 가서야 발견할 수 있다.
- 삭제된 함수는 public으로 선언하는 것이 관례이다.
- 멤버 함수 호출 시, C++은 함수의 접근성을 먼저 체크한 후 삭제 여부를 체크한다.
- 몇몇 컴파일러는 private를 호출했음을 먼저 에러로 고지하며, 그래서는 delete 된 함수인지 바로 알기 힘들다.
- 삭제된 함수는 어떤 함수도 삭제할 수 있다.
- C++98 방식은 멤버 함수에만 적용할 수 있다.
bool isLucky(int number);
// 암시적 변환으로 인해 아래의 함수는 모두 컴파일 성공한다.
if(isLucky('a')) ...
if(isLucky(true)) ...
if(isLucky(3.5)) ...
// 아래처럼 하면 해결할 수 있다.
bool isLucky(int number);
bool isLucky(char) = delete;
bool isLucky(bool) = delete;
bool isLucky(double) = delete;
- 삭제된 함수들은 사용할 수 없더라도 프로그램의 일부이다.
- 즉, 함수 오버로드의 후보이다.
- 그러므로 위의 문제가 해결이 되는 것이다.
- 삭제된 함수는 템플릿 인스턴스화를 방지할 수 있다.
template<typename T>
void processPointer(T* ptr);
// 특별한 포인터 두 가지(void*, char*)에 대해 호출을 거부하고 싶다.
// C++11에서는 delete 처리하면 된다.
template<>
void processPointer<void>(void*) = delete;
template<>
void processPointer<void>(char*) = delete;
// const 버전도 delete 처리한다.
template<>
void processPointer<void>(const void*) = delete;
template<>
void processPointer<void>(const char*) = delete;
// 더 철저히 하려면
// const volatile void* / const volatile char*
// wchar_t, char16_t, char32_t
// 들도 delete 처리해야 할 것이다.
// C++98 관행으로는 처리할 수 없다.
class Widget
{
public:
...
template<typename T>
void processPointer(T* ptr)
{ ... }
private:
template<>
void processPointer<void>(void*); // 에러!
};
- private로 정의 없이 선언이 불가능한 이유
- 템플릿 특수화는 반드시 클래스 범위가 아니라 네임스페이스 범위에서 작성해야 한다는 규칙이 있기 때문이다.
728x90
'Effective C++ > Effective Modern C++' 카테고리의 다른 글
[Effective Modern C++] 13. const_iterator 선호하기 (0) | 2025.02.21 |
---|---|
[Effective Modern C++] 12. override 키워드와 참조 한정사(reference qualifier) (0) | 2025.02.20 |
[Effective Modern C++] 10. enum class (0) | 2025.02.18 |
[Effective Modern C++] 9. typedef vs using (0) | 2025.02.17 |
[Effective Modern C++] 8. nullptr (0) | 2025.02.14 |
Comments