2009-12-05 4 views
6

정확하게 이해한다면 구성을 구현하는 데 적어도 두 가지 다른 방법이 있습니다. (스마트 포인터 구현의 경우는 단순화를 위해 제외 나는 거의 STL을 사용하고 배울 수있는 욕망을하지 않습니다.).C++에서 클래스 구성을 구현하는 방법은 무엇입니까?

는 이제 위키 백과 example를 살펴 보자 :

class Car 
{ 
    private: 
    Carburetor* itsCarb; 
    public: 
    Car() {itsCarb=new Carburetor();} 
    virtual ~Car() {delete itsCarb;} 
}; 

그래서를, 그것은 하나의 방법입니다 - 개체을 전용 멤버로 가리키는 포인터가 있습니다. 하나 같이 그것을 다시 작성할 수 있습니다 :이 경우

class Car 
{ 
    private: 
    Carburetor itsCarb; 
}; 

우리는 private 멤버로 객체 자체를 가지고있다. (그런데, 나는이 개체를 전문 용어의 관점에서 객체라고 부른다.)

두 번째 경우에는 암시 적으로 기본 생성자를 호출 할 필요는 없습니다 (기본값이 아닌 생성자를 호출해야하는 경우 이니셜 라이저 목록에서 가능) 및 소멸자. 그러나 큰 문제는 아닙니다 ...

그리고 물론이 두 경우는 좀 더 분명히 다릅니다. 예를 들어, Car 클래스의 const 메소드에서 Carburetor 인스턴스의 비 const 메소드를 두 번째 케이스에서 호출하는 것은 금지되어 있습니다 ...

사용할 "규칙"이 있습니까? 내가 놓친 게 있니?

+1

"Car 클래스의 const 메소드에서 Carburetor 인스턴스의 비 const 메소드를 호출하는 것은 금지되어 있습니다"라고 생각합니다. –

+0

@ Laurence Ooops. 당신은 물론 맞습니다 ... – Wildcat

+8

"[나는] [STL]을 배우려는 욕구가 없습니다." 뭐? 당신은 STL을 무시함으로써 C++의 거대한 부분을 놓치고 있습니다. – rlbond

답변

7

이 경우 우리는 개인 회원으로 개체 자체를 가지고 있습니다. (그런데이 개체를 객체로 부르는 것은 용어의 관점에서 쓰는 것입니까?)

예 "객체"또는 "인스턴스"라고 말할 수 있습니다.

"포인터로"대신 "값으로"데이터 멤버를 포함하는 것에 대해서도 말할 수 있습니다 ("포인터로"및 "값으로"는 매개 변수를 전달하는 일반적인 방법이므로 사람들이 이해할 것으로 기대합니다). 이러한 용어는 데이터 멤버에게 적용됩니다).

어떤 규칙을 사용하면 좋을까요? 내가 놓친 게 있니?

인스턴스가 둘 이상의 컨테이너에서 공유되는 경우 각 컨테이너는 값 대신 포인터로이를 포함해야합니다. 예를 들어 Employee에 Boss 인스턴스가있는 경우 여러 Employee 인스턴스가 동일한 Boss를 공유하는 경우 Boss를 포인터로 포함합니다.

데이터 멤버의 수명이 컨테이너의 수명과 같지 않은 경우 포인터로 포함합니다 (예 : 데이터 멤버가 컨테이너 다음에 인스턴스화되거나 컨테이너 이전에 소멸되거나 파괴 된 경우) 또는 컨테이너의 수명 기간 동안 또는 데이터 멤버가 null 인 경우에 의미가있는 경우 재 작성됩니다.

데이터 멤버의 형식이 추상 기본 클래스 인 경우 값 대신 포인터 (또는 참조)로 포함해야하는 또 다른 시간입니다.

포인터를 포함하는 또 다른 이유는 컨테이너를 다시 컴파일하지 않고 데이터 멤버의 구현을 변경할 수있게하는 것입니다. 예를 들어 Car와 Carburetor가 두 개의 서로 다른 DLL에 정의 된 경우 Carburetor를 포인터로 포함 할 수 있습니다. Car.dll을 다시 작성하지 않고 다른 Carburetor.dll을 설치하여 Carburetor 구현을 변경할 수 있습니다.

+0

+1은 지금까지 간과 된 것으로 보이는 참조를 언급합니다. – Glen

3

구성 : 가능하면 회원을 선호하십시오. 다형성이 필요하거나 전달 선언이 사용될 때 포인터를 사용하십시오. 물론 스마트 포인터가 없으면 포인터를 사용할 때 수동 메모리 관리가 필요합니다.

1

Carb와 Car의 수명이 같으면 비 포인터 양식이 더 좋습니다. Car에서 Carb를 교체해야한다면 포인터 버전을 선택할 것입니다.

8

저는 Car.h에서 Carburettor.h를 #include해야하기 때문에 첫 번째 경우를 선호합니다. Carburettor는 비공개 멤버이기 때문에 실제 Car 구현 코드 이외의 위치에 정의를 포함하면 안됩니다. Carburettor 클래스의 사용은 명확하게 구현 세부 사항이며 Car 객체를 사용하는 외부 객체는 다른 필수가 아닌 종속성을 포함하여 걱정할 필요가 없습니다. 포인터를 사용하면 Car.h에서 Carburettor의 전방 선언을 사용해야합니다.

+0

이것은 두 경우 모두 동일하므로이 것을 downvoted. –

+0

당신은 좀 더 구체적 일 수 있습니까, 임 꽤 확신 할 수 없습니까? – nico

+2

두 경우 모두 동일합니다. nicolascormier가 지적했듯이 헤더 파일을 포함하지 않으려면 전달 선언을 사용할 수 있습니다. 아마 downvoting하기 전에 대답을 이해해야합니다. –

0

일반적으로 비 포인터 버전은 사용 및 유지 관리가 더 쉽습니다.

하지만 어떤 경우에는 사용할 수 없습니다. 예를 들어 자동차에 기화기가 여러 개 있고 배열에 넣으려는 경우 Carburetor 생성자에 인수가 필요합니다. 새롭게 작성하여 포인터로 저장해야합니다.

관련 문제