본문 바로가기

Effective C++7

Effective C++ (46) ~ (50) 46) 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자. 항목 24에서 모든 매개변수에 대해서 암시적 타입 변환이 되도록 만들기 위해서는 비멤버 함수밖에 방법이 없다는 이야기를 했었다. 이것을 템플릿으로 확장해보자. template class Rational { public: Rational(const T& numerator = 0, const T& denominator = 1); // 매개변수가 참조자로 전달되는 이유는 항목 20 const T numerator() const; const T denominator() const; }; template const Rational operator*(const Rational& lhs, const Rational& rhs) { ... 2021. 8. 28.
Effective C++ (41) ~ (45) 7. 템플릿과 일반화 프로그래밍 41) 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타임 다형성부터 클래스와 템플릿은 모두 인터페이스와 다형성을 지원한다. 명시적 인터페이스 : 소스 코드에 명시적으로 드러나는 인터페이스 런타임 다형성 : 실제 호출이 동적 타입 기반으로 런타임에 결정되는 경우 암시적 인터페이스 : 제대로 컴파일 되기 위해 필요한 ‘유효한’ 표현식 컴파일 타임 다형성 : 컴파일 도중 인스턴스화가 진행되는 함수 템플릿에 어떤 템플릿 매개 변수가 들어가느냐에 따라 호출되는 함수가 달라지는 경우 클래스의 경우 인터페이스는 명시적이고 함수의 시그니처를 중심으로 구성되어 있다. 다형성은 런타임에 가상함수를 통해 나타난다. 템플릿 매개변수의 경우 인터페이스는 암시적이고 유효 표현식을 기반으.. 2021. 8. 26.
Effective C++ (36) ~ (40) 36) 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물! 비가상 함수는 정적 바인딩, 가상 함수는 동적 바인딩으로 이루어진다. 만약 비 가상 함수를 재정의하고 호출한다면 호출하는 객체의 타입에따라 동작이 달라진다. 따라서 상속받은 비가상 함수는 절대로 재정의하지 말자. 37) 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자 기본값을 정의해둔 가상 함수의 매개변수는 절대로 상속하면서 파생 클래스에서 값이 달라지거나 하지 않도록 주의하자. 가상 함수 자체는 동적으로 바인딩되어 있지만 기본 매개변수는 정적으로 바인딩되어있다. 이는 런타임 효율을 높이기 위해서이다. 따라서 파생 클래스에 정의된 가상 함수를 사용하면서 매개 변수는 기본 클래스의 매개변수를 사용하게 될 수.. 2021. 8. 25.
Effective C++ (26) ~ (30) 5. 구현 26) 변수 정의는 최대한 늦추자 객체를 선언해 기본 생성한 후 대입하는 방법은 비효율적이다. 기본 생성자를 건너뛸 수 있다면 건너 뛰고 초기화 인자를 얻을 때까지 정의를 미루자. 루프에 대해서는 다음 두가지 선택지가 있다. // A 방법 Widget w; for(int i = 0; i < n; ++i) { w = Widget(i); // i에 따라 달라지는 값 } // B 방법 for(int i = 0; i < n; ++i) { Widget w(i); // i에 따라 달라지는 값 } A 방법은 생성자 1번 + 소멸자 1번 + 대입 n번 B 방법은 생성자 n번 + 소멸자 n번이 불린다. 만약 대입 비용이 생성자+소멸자 쌍보다 적게 드는 경우엔 A가 효율이 좋다. 하지만 그렇지 않을 때엔 B가 .. 2021. 8. 22.
Effective C++ (11) ~ (15) 2. 생성자, 소멸자 및 대입 연산자 11) operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 자기대입이란 어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것이다. Widget w; w = w; 별 문제가 없어보이지만 문제가 있다는 게 가장 큰 문제이다. 대입 연산자 내에서 어떤 동작을 할지 모르기 때문이다. 따라서 대입 연산자에서는 반드시 일치성 검사를 넣어 다음과 같이 구현해야 한다. Widget& Widget::operator=(const Widget& rhs) { if(this == &rhs) return *this; ... } 혹은 예외 안정성을 높인 다음과 같은 방법도 있다 Widget& Widget::operator=(const Widget& rhs) { Bitmap *.. 2021. 8. 12.
Effective C++ (6) ~ (10) 2. 생성자, 소멸자 및 대입 연산자 6) #컴파일러가 만들어낸 함수가 필요 없다면 확실히 금지시키자 복사 생성자와 복사 대입 연산자는 사용자가 선언하지 않을 때에도 컴파일러가 자동으로 만들어내는 대표적인 두 함수이다. 이 둘의 사용을 금지하기 위해 반드시 private으로 선언하자. 이 때 매개변수 이름은 생략해도 되고, 이렇게 선언된 기본 클래스를 만들어 상속하도록 활용할 수도 있다. 7) 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 C++ 의 규정에 따르면, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때, 소멸자가 비 가상으로 선언되어 있다면 미정의 동작이 발생한다. 이를 막기 위해 언제나 기본 클래스에는 소멸자를 가상으로 선언한다면, 어떤 포인터로 객체를 삭제.. 2021. 8. 9.
반응형