2010-02-27 3 views
4

다른 클래스의 객체에 boost :: shared_ptrs라는 멤버 변수가있는 C++ 클래스가 있습니다 (dll 프로젝트 내부). 그것들을 클래스 생성자 내부에 할당하거나 별도의 init() 함수를 사용하는 것이 더 낫습니다.생성자, 단위 테스트에서 공유 ptrs (boost) 할당

boost :: shared_ptr 내부의 T에 대한 포인터의 기본값이 NULL이라고 가정합니다. 그래서 생성자 내부에서 아무것도하지 않으면 :: shared_ptr의 get()은 Init() 함수를 호출하기 전에 NULL을 반환합니다.

또한 Init (예외)를 catch해야하거나이 Init() 호출자에게 예외를 잡으라고 알리는 것이 좋은지, 할당 문의 새에서 메모리 할당 문제가있는 경우 어떻게됩니까? boost :: shared_ptr a (새 T);

단위 테스트 내부에서 메모리 할당 예외를 시뮬레이트하는 표준 접근법이 있습니까? 모든 오브젝트가 올바르게 할당 해제 된 것을보십시오

답변

2

저는 멤버 변수가 다른 클래스의 객체에 boost :: shared_ptrs 인 C++ 클래스가 있습니다 (dll 프로젝트 내부). 그것들을 클래스 생성자 내부에 할당하거나 별도의 init() 함수를 사용하는 것이 더 낫습니다.

생성자에서 모든 작업을하는 것이 일반적으로 좋습니다.
after (후)라고하는 init() 함수를 사용하면 생성 후 객체가 유효하지 않음을 의미하므로 init()이 호출되었는지 여부를 나타내는 상태 플래그를 유지하고 public 메서드가 호출 될 때마다 해당 플래그를 확인해야합니다 초기화되지 않은 객체에 대해 적절한 작업을 수행하십시오.

boost :: shared_ptr 내부의 T에 대한 포인터의 기본값이 NULL이라고 가정합니다. 그래서 생성자 내부에서 아무것도하지 않으면 :: shared_ptr의 get()은 Init() 함수를 호출하기 전에 NULL을 반환합니다.

예 : shared_ptr의 기본 생성자는이를 NULL로 초기화합니다.

또한, 할당 문 중 하나에서 새로운 것에 대한 메모리 할당 문제가있을 때 (Init에서 예외를 잡을 경우) 또는이 Init() 호출자에게 예외? boost :: shared_ptr a (새로운 T);

당신이 생성자가있는 경우 : 다음 unitialised 객체가 닿을 수없는 동안, (소멸자를 통해) 제대로 파괴됩니다 건설되었던 모든 회원들, 그리고 현재 개체에 대한 메모리가 할당되지 않을 경우로 출시됩니다 (이니셜 라이저 목록을 사용하는 또 다른 좋은 이유).

init()을 사용하는 경우 : 예외를 catch하여 개체를 올바르게 정리하고 메모리를 해제해야합니다. 객체의 복잡성에 따라 init 내부에서이 작업을 수행 할 수 있지만 (올바르게 수행하기는 어렵습니다) 호출자가 수행해야합니다. 그런 다음 생성자에서 예외가 throw 된 경우와 동일한 작업을 수행해야합니다 (사용법에 따라 다름).

단위 테스트 내에서 메모리 할당 예외를 시뮬레이트하는 표준 접근법이 있습니까? 모든 오브젝트가 올바르게 할당 해제 된 것을보십시오

오브젝트를 할당하기 위해 팩토리 오브젝트를 사용할 수 있습니다.
팩토리 객체를 생성자에 전달합니다. 건설 중에 예외를 시뮬레이트하기를 원한다면 적절한 예외를 생성하는 모의 팩토리를 전달하면된다.

1

멤버 할당을 위해 이니셜 라이저 목록을 사용하십시오. 그것들은 선호되는 (때로는 유일한 접근법입니다).

개체를 만드는 동안 문제가 발생하면 예외가 발생하고 복구가됩니다. 또는 멤버 함수가 호출 될 때마다 확인해야만 사용중인 객체가 유효한지 확인하기 위해 valid 플래그를 유지해야합니다.

언제든지 예외를 찾아보고 할 수 있습니다. 탈퇴가 실패하면 예외를 던져서 dtor에서 처리하고보고하고 계속 진행하는 것이 이상적입니다.

1

첫 번째 질문에서 포인터가 유효한지 확인하려면 초기화 프로그램 목록을 사용하는 것이 가장 이상적입니다. 이렇게하지 않으면 잠재적으로 포인터를 사용하기 전에 포인터가 유효한지 항상 확인해야합니다. 특히 호출 코드를 호출 코드로 남겨 두는 경우에는 init()

다른 한편으로는 순수 가상을 호출하여 설정할 수있는 경우에만이 작업을 수행 할 수 있습니다. init() 방법을 사용하십시오.

초기화 할 때, 나는 잡을 수 있고 다시 살리거나 단순히 잡을 수 없다고 생각합니다. 어느 쪽이든 그것은 호출자가 메모리 할당 예외를 잡는 것이 바람직하다고 생각합니다.

왜 객체 중 하나에서 init()을 호출하면 메모리 할당 예외를 테스트하려고하는지 볼 수 있습니다. 여기 접근법은 항상 전화를 던지는 스텁 객체를 대체하는 것일 수도 있습니다 init()

왜 공유 포인터 (원시 포인터, 아마도 어쩌면)의 할당을 확인하고 싶은지 알 수 없습니다. 포인터는 공유 포인터를 참조 할 수있는 동안 정의에 따라 공유 포인터를 공유하므로 아직 파손되지 않습니다.

참조 카운트를 확인하거나 뾰족한 개체를 설정하고 테스트를 통해 모니터 할 수있는 세마포를 지울 수 있습니다. 어떻게 든 그 요점을 놓치고 있습니까?

+0

그 답변을 주셔서 감사합니다. Robin, 단위 테스트 중에 참조 횟수를 사용해야합니다. 나는 스텁을 만드는 아이디어를 좋아한다. – Kamal

+0

@Kamal, 컴파일러는 나중에 초기화 된 다른 멤버가 던져지면 초기화 멤버의 소멸자를 호출한다. –

관련 문제