모던 C++ 디자인 패턴 책에서 프로토 타입에 대한 내용 중 도저히 이해가 안가서 질문올립니다.
먼저 타입은
struct Address
{
string street, city;
int suite;
}
struct Contact
{
string name;
Address *address;
}
인 상황이고
문제의 내용은
======================================================================
이 경우 복제 생성자를 정의하는데 두 가지 방법이 있다. 금방 떠오르는 방법은 다음과 같이 구현하는 것이다.
Contact(const Contact& other)
: name{other.name}
{
address = new Address( // ------------------------ {1}
other.address->street,
other.address->city,
other.address->suite
);
}
안타깝게도 위 코드는 충분히 범용적이지 않다. - 중략 -
여기에서 상식적인 대응은 Address에 복제 생성자를 정의하는 것이다. 이 예에서는 아래와 같이 쉽게 정의할 수 있다.
Address(const string& street, const string& city, const int suite) // -------------------{2}
: street{street},
city{city},
suite{suite} {}
그러면 Conatct의 생성자를 재활용하여 아래와 같이 복제 생성자를 이용하게 할 수 있다.
Contact(const Conatct& other)
: name{other.name}
, address{ new Address{*other.address} } {} // ------------------------{3}
======================================================================
위 내용에서
{2}가 복제 생성자(copy constructor 말하는 것 같은데)가 아니라 인수를 받는 생성자고 {3}에서 호출되는게 아니라 {1}에서나 호출되는 코드 아닌가요?
복사생성자면 Address(const Address& other){...}로 정의되어야 하지 않나요
살인병기김점순의독감자
바로 밑에 또다른 오류같은데
Contact john = worker;
Address에 복제 생성자와 대입 연산자의 구현이 누락되었다고 하자(단 Conatact는 구현되어 있다). 이 코드는 컴파일 되는데 아무런 문제가 없다. 복제 생성자만 사용한다면 상황이 조금 더 낫다. 존재하지 않는 복제 생성자의 호출이 있으면 에러가 발생하여 문제를 인지할 수 있다. 하지만 대입 연산자는 모든 상황에서 디폴트 동작이 정해져 있으므로 적절한 대입 연산자를 정의하지 않았더라도 컴파일되고 실행되어 버린다.
???? user-defined 소멸자가 있지 않는 한 복사 생성자도 디폴트가 있고 초기화 시 대입은 대입 연산자가 호출되는게 아니라 복사 생성자잖아요. 제가 알고 있는게 다 잘못된건가요?
동탄올리버
크로스 체킹 해보셈
https://refactoring.guru/ko/design-patterns/prototype
동탄올리버
https://refactoring.guru/ko/design-patterns/prototype/cpp/example
집에가게해줘
저도 잘 모르지만..
책에서 하는 말은
"{1} 방식대로 하면 생성자 매개변수로 하나하나 다 넣어줘야하니 범용적이지 않다! 그러니 {2}처럼 만들고 {3}처럼 쓰면 된다!"
라는거 같은데 뭔가 말이 반대가 된 듯합니다.
"{2} 방식대로 만들고 {1} 처럼 쓰면 범용적이지 않다! 그러니 {Address(const Address& other)}처럼 만들고 {3}처럼 쓰면 된다!"가 맞지 않나 싶네요.
하지만 책 저자분이 이런 실수를 하지는 않았을꺼 같으니... 내가 틀리지 않았을까! 싶네요