@ 16. 1 ~ 17. 1/Effective C++
-
항목 35 : 가상 함수 대신 쓸 것들도 생각해 두는 자세를 ..@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 25. 14:49
비가상 함수 인터페이스(NVI 관용구) 가상 함수의 랩퍼라고들 함. class A { private: virtual int dohelath() const //가상함수를 private로 설정하고 { int num=3; return num; } public: int health() const //가상함수를 랩퍼하는 함수 { //전에 할일을 넣을 수 있고 int val=dohelath(); //가상함수를 호출한다. //dohealth()가 끝난 뒤에 할일을 넣을 수 있다. return val; } }; class B : public A { public: void showhealth() { cout
-
항목 10 : 대입 연산자는 *this의 참조자를 반환한다@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 15. 22:15
x=(y=(z=15)); 이렇게 대입연산이 사슬처럼 엮이려면 대입 연산자가 좌변 인자에 대한 참조자를 반환하도록 구현되어야 한다. 즉 z=15에서 z가 참조 반환되어 y=에 들어가고 y가 참조반환되어 x=에 들어간다. 즉 return *this; operator= operator+= 특히 operator=에서는 자기대입에 대한 처리가 빠지지 않도록 한다. class B { public: int num; B() { num=0; } }; class A { public: B *num; public: A() { num=new B; } ~A(){} //첫번째 방법 일치성 검사 A& operator=(const A& rhs) { if(this==&rhs) { return *this; } delete num; num..
-
항목 7:가상 소멸자@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 14. 23:20
가상 소멸자를 하는 이유는 어떤 함수(파생클래스를 반환하는데 반환인수는 기본클래스) 가 반환하는 포인터가 파생클래스 객체애 대한 포인터라는 점과 이 포인터가 가리키는 객체가 삭제될때 기본 클래스 포인터를 통해 삭제된다는 점 A B : public A 일때 A* return() 일 경우.. A부분은 저 세상(delete)되는데 B부분은 남아 있다 .. 가상함수를 하나라도 가진 클래스는 가상 소멸자를 가져야한다. 가상 함수가 들어가게 되면 객체 크기가 커진다. 어떤 객체에 대해 어떤 가상함수가 호출되려고 하면 호출되는 실제 함수는 그 객체의 vptr(가상함수 테이블 포인터)가 가리키는 vtbl(가상 함수 테이블)에 따라 결정된다 vtbl에 있는 함수 포인터들 중 적절한 것이 연결되는 것. 순수가상소멸자 A클..
-
항목6 : 복사생성자 및 대입연산자 제한@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 14. 22:42
기존의 private 상태로 복사생성자(const 복사생성자&); 대입연산자& operator=(const 대입연산자&); 였던 방법말고도.. 상속을 활용하면서 class A { protected: A(){} ~A(){} private: A(const A&); //복사 생성자 A& operator=(const A&); //대입연산자 }; class B : private A { public: B(){} int num; }; 이런식으로 활용한다..
-
항목 37 : 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자@ 16. 1 ~ 17. 1/Effective C++ 2014. 6. 2. 23:15
기본클래스 *ptr1; 기본클래스 *ptr2 = new 첫번째 상속클래스 기본클래스 *ptr3 = new 두번째 상속클래스 여기서 ptr1, ptr2, ptr3는 모두 기본 클래스에 대한 포인터로 선언되어 있기 때문에 각각의 정적 타입도 모두 이 타입이다 정적 타입이란 프로그램소스 안에 선언문을 통해 그 객체가 갖는 타입을 말한다. 정적타입이 기본클래스 일뿐.. 동적타입은 ptr2의 동적 타입은 첫번째 상속클래스 ptr3는 두번째 상속클래스 ptr1은 없기 때문에 없다. 동적 타입은 프로그램이 실행되는 도중에 바뀔 수 있다. 대게 대입떄.. ptr1=ptr2 // ptr1의 동적 타입은 이제 첫번째 클래스가 된다. 가상함수는 동적으로 바인딩된다. 호출이 일어난 객체의 동적 타입에 따라 어떤 가상함수가 호..
-
항목 33 : 상속된 이름을 숨기는 일은 피하자@ 16. 1 ~ 17. 1/Effective C++ 2014. 6. 1. 20:30
유효범위는 우선 지역범위 그다음에 바깥쪽 유효범위를.. 파생클래스의 유효범위가 기본 클래스의 유효범위안에 중첩되어있다. 기본 클래스에 있는 함수들은 모두 파생 클래스에 있는 함수(동일한 이름)에 가려지고 만다. 기본 클래스와 파생 클래스에 있는 함수(이름이 같은, 오버로드 할 시..)들이 받아들이는 매개변수 타입이 다르거나 말거나 거리낌없이 가려진다. 심지어 가상함수인지 비가상함수 인지의 여부도 상관이 없다.. 그 이유는 멀리 떨어져 있는 기본 클래스로부터 오버로드 버전을 상속시키는 경우는 막겠다. 그러나 가능한 방법이 있다. using 기본클래스::함수명; 이런식으로 public: 아래에 선언을 하면 된다. 주의해야할것은 private 상속일시 using은 그 이름에 해당되는 것들이 모두 파생클래스로 ..
-
항목4 : 객체를 사용하기 전에 반드시 그 객체를 초기화하자@ 16. 1 ~ 17. 1/Effective C++ 2013. 8. 25. 21:16
int x; 어떤 상황에서는 x의 값이 확실히 초기화되지만 또 다른 상황에서는 그것이 보장되지 않는다는 것입니다. 어떤 플랫폼의 경우에는 미초기화 객체를 읽기만 해도 프로그램이 서 버리기도 합니다. 가장 좋은 방법은 모든 객체를 사용하기 전에 항상 초기화하는 것이다. int x =0; const char *text="welcome to"; double d; cin >> d; //입력스트림에서 읽음으로써 초기화 수행 이런 부분을 제외하고 나면 c++ 초기화의 나머지 부분은 생성자로 귀결된다. 초기화를 하면서 대입과 초기화를 헷갈리지 않는 것이 가장 중요하다. 생성자에서 초기화는 멤버 초기화 리스트를 사용하는 것이며 그 외의것은 대입이 되고 있는 것이다. class Rational{ public: Ratio..