본문 바로가기

전체 글57

항목 45. "호환되는 모든 타입"을 받아들이는 데는 멤버 함수 템플릿이 직방! 1. 스마트포인터 vs 보통의 포인터 1) 스마트포인터는 일반포인터처럼 동작하나, 추가적인 기능을 덤으로 갖고 있다. (ex. auto_ptr, tr1::shared_ptr, list::iterator 등이 있다.) 하지만 보통의 포인터도 스마트 포인터로 대신할 수 없는 특징이 있다. 그중 하나가 암시적 변환을 지원한다는 점이다. 2) 보통의 포인터에서 파생클래스는 기본클래스로 변환이 가능하며, 비상수객체에서 상수객체로서의 암시적 변환이 가능하다는 것이다. 스마트포인터는 암시적변환기능을 지원하지 않는다. 왜냐하면 컴파일러가 두 스마트 포인터간에 연관성을 찾지 못하기 때문이다. 하지만, 스마트포인터는 "멤버 함수 템플릿"을 사용하여 암시적 변환 기능을 얻어 낼 수 있다. 2. 멤버 함수 템플릿 templa.. 2020. 3. 24.
항목 44. 매개변수에 독립적인 코드는 템플릿으로부터 분리시키자 1. 템플릿의 비대화 1) 문제점 : 템플릿을 잘 못쓰면 중복문제로 이진코드의 비대화 가능성이 있다. 2) 해결방법 : "공통성 및 가변성 분석" 을 사용한다. 3) 공통성 및 가변성 : 함수 측면에서 살펴보면, 두함수에서 공통적으로 사용되는 로직은 따로 함수화 하여, 그 함수를 각각의 함수에서 호출해주는 방식이라고 생각하면 된다. * 템플릿도 정확히 동일한 방법으로 코드중복을 막으면된다. 예제를 살펴보자. template // T타입의 객체를 원소로 하는 n행 n열의 행렬을 나타내는 템플릿 class SquareMatrix { public : void invert(); // 주어진 행렬을 그 저장공간에서 역행렬로 만든다. }; *풀이 - 고정 크기의 정방행렬을 나타내는 클래스 템플릿 - 템플릿은 T라는.. 2020. 3. 24.
항목 43. 템플릿으로 만들어진 기본 클래스 안의 이름에 접근하는 방법을 알아두자 1. 결론 1) 기본 클래스 템플릿은 언제라도 특수화 될 수 있다. 2) 컴파일러는 특수화버전의 인터페이스와 기본클래스 템플릿과 같을 수 없다는 것을 인식한다. 3) 기본클래스 템플릿을 상속받은 파생클래스 템플릿은 2)과 같은이유로 기본클래스안의 이름을 접근하지 않는다. * 즉, 템플릿 기반클래스를 상속받을때에는 상속의 기본메커니즘(컴파일타임 상속체계)이 끊긴다. 4) 따라서, 기본클래스 템플릿안의 이름에 접근하는 방법을 알아둬야한다. 예제 1) 기본 클래스 템플릿 class CompanyA{ //회사 A public : ... void sendCleartext(const string& msg); void sendEncrypted(const string& msg); ... }; class CompanyB.. 2020. 3. 19.
항목 42. typename의 두 가지 의미를 제대로 파악하자 1. class와 typename 공통점 템플릿 매개변수 선언시 class와 typename은 완전히 동일하다. template class Widget; // class 사용 template class Widget; /typename 사용 2. class와 typename 차이점 하지만 class 와 typename 키워드가 다르게 사용되는 경우가 있다. template void print2nd(const C& container) //컨테이너에 들어 있는 2번째 원소를 출력합니다. { if (container.size() >= 2 ) { C::const_iterator iter(container.begin()); //첫째 원소에 대한 반복자를 얻습니다. ++iter; // 두번째원소로 iter를 옮깁니다.. 2020. 3. 17.
항목 41. 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타임 다형성부터 1. 클래스의 특성 class Wdiget { public : Widget(); virtual ~Widget(); virtual std::size_t size() const; virtual void normalize(); void swap(Widget& other); … }; void doProcessing(Widget& w) { if (w.size() > 10 && w != someNastyWidget) { Widget temp(w); temp.normalize(); temp.swap(w); } } *풀이 1. w는 Widget 인터페이스를 제공해야된다. Widget 인터페이스가 소스코드에 명시되어 있다. -> 명시적 인터페이스 2. Widget의 가상함수는 실행도중 어떤것이 호출될지 결정된다. -> .. 2020. 3. 17.
항목 40. 다중 상속은 심사숙고해서 사용하자 1. 다중상속의 문제점 개발자들 사이에서 다중상속에 관해 크게 2가지 견해로 갈린다. 1. 단일상속이 좋다면, 다중상속은 더 좋다. 2. 단이상속은 좋지만, 다중상속은 골칫덩어리다. '다중 상속'하면 바로 우리 머리에 들어와야할 사실은 둘이상의 기본 클래스로부터 똑같은 이름을 물려받을 가능성이 생긴다는것이다. 아래 예시코드를 보자. class BorrowableItem { public : void checkOut(); }; class ElectronicGadget { private : bool checkOut() const; }; class MP3Player : public BorrowableItem, public ElectronicGadget { … }; MP3Player mp; mp.checkOut(.. 2020. 3. 16.