{ 이번 항목은 좀 역발상으로 이야기를 쫒아 본다. 기반 클래스의 디스트럭터가 public 과 virtual 이라면, 파생 클래스에게 어떠한 영향을 미치는가? 1. 객체 생성이 자유롭다. 2. 객체의 완전한 소멸이 기반 객체의 포인터로도 가능하다. 그렇다면, protected 와 non-virtual 이라면? 1. 객체 생성이 friend나 상속 기반에서만 이루어 진다. 2. 객체의 완전한 소멸은 항상, 파생 클래스에서만 가능하다. 이 두가지 방식을 따라야 하는 이유는 무엇인가? 메모리가 누수될 가능성이 무척 커진다. 이해 못하겠다. 예제를 보여 달라. #include #include // example class Base { public: ~Base() // non virtual { std::cout
책 정리 검색 결과
{ 왜냐하면, 파생 객체의 생성자 호출 순서는 항상 기반 객체이기 때문이다. 잘 이해가 안간다....? 그러니까 기반 객체의 생성자가 호출 될 때 가상 함수가 호출 되어 지면, 파생 객체는 아직 만들어 지지 않았기 때문에, 파생 객체의 함수가 호출 되지 않고, 기반의 함수가 호출 된다. 이는 개발자에게 가독성은 물론이거나와 몹시 어렵다는 느낌을 줄 수 밖에 없다. 디스트럭트 역시 마찬가지다. 예제는? #include #include // example class Base { public: ~Base() {} Base( char *__p ) { Draw(__p); } public: virtual void Draw(char *) { std::cout
{ 왜냐하면 불필요한 작업을 줄일 수 있기 때문이다. 무엇이 불필요한 작업인가? 변수는 생성과 동시에 초기화값을 대입하면, 한번의 생성으로 값을 셋팅 할 수 있다. 그러니 값을 생성 하고 난 뒤에 값을 대입한다면, 불필요한 작업이 되는 것이다. 그래서 모두 초기화 목록에서 초기화 했는데, 보기가 어렵더라? 맞는 말이다. 변수가 많은 경우에는 특정 함수로 빼서 사용 하는게 더 간편하고 안전하다. 너무 이른 최적화가 아닌가? 이건 최적화 축에도 못낀다. 적당한 선에서 타협하여, 함수로 뺄찌 초기화 리스트에 넣을지 결정하는게 좋을 것 같다. }
{ 왜냐하면 멤버 변수의 정의순으로 초기화 하기 때문이다. #include #include class name { public: ~name() {} name(char *__pfirst_name, char *__plast_name ) : last_name_(__plast_name) , first_name_(__pfirst_name) , full_name_( first_name_ + " " + last_name_ ) {} const std::string& get_full_name() { return full_name_; } private: std::string full_name_; std::string first_name_; std::string last_name_; }; int main( void ) { ..
{ 왜냐하면 C++의 이름검색 알고리즘 때문이다. 검색하는 네임스페이스 안에, 같은 이름의 함수가 발견 된다면, 그 곳에서 검색이 멈추고, 더 이상 찾으려고 하지 않는다. Effective C++ 이나 Exeptional C++ 보면 자세히 나오는데, 그것을 참고 하는게 좋을 듯 싶다. 이름 검색 알고리즘 관련링크 http://www.ikpil.com/670 }
{ 왜 같이 제공해 주어야 하는가? 컴파일러가 하는 일 중에 코드를 생성해 주는 일도 있다. 컴파일러의 코드의 생성은 여러 가지 일들이 있다. 그 중에서 new 가 실패 했을 경우, 자동으로 delete문을 만들어 주는 부분이 있는데, 만약 new와 같은 쌍의 delete가 없다면, delete를 호출하는 코드를 추가해 주지 않는다. 그렇기 때문에, 항상 같이 제공해 주어야 한다. 예외적으로 메모리를 생성하지 못하는 new의 경우 delete를 만들지 않아도 상관이 없다. 왜냐하면 메모리가 세어 나가는게 아니기 때문이다. 관련링크 http://www.debuglab.com/knowledge/newoperation.html }
최근댓글