2009-07-29 5 views
5

나는 유사한 인터페이스 클래스가 구체적인 클래스 AImplementation의 인스턴스를 생성합니다. 예 : 그런 다음가장 좋은 방법 ++ 인터페이스

class IInterface 
{ 
public: 

    virtual ~IInterface() {} 

    static std::tr1::shared_ptr<IInterface> create(); // implementation in .cpp 
    virtual methodA() = 0; 

    virtual methodB() = 0; 

}; 

내가 지금 같은 주에있는 인터페이스를 사용할 수있을 것입니다 :

int main() 
{ 
    AImplementation* ai = new AIImplementation(); 
} 

또는 더 나은 다음과 같은 인터페이스의 멤버 함수를 "만드는"공장을 넣어하는 것입니다

int main() 
{ 
    std::tr1::shared_ptr<IInterface> test(IInterface::create()); 
} 

첫 번째 옵션은 일반적인 관행 (해당 권한을 말하지 않는 것) 인 것처럼 보입니다. 그러나 두 번째 옵션은 "Effective C++"에서 유래되었습니다.

+0

언어의 정확성에 대한 몇 가지 메모가 있습니다. C++에서는 메소드가없고 멤버 함수가 있습니다. – Artyom

+1

다음과 같이 main()을 작성합니다. 'int main() { IInterface * i = new AIImplementation(); }' –

답변

8

인터페이스를 사용하는 가장 일반적인 이유 중 하나는 구체적 구현이 아닌 "추상화에 맞서 프로그램"할 수 있기 때문입니다.

가장 큰 이점은 나머지 코드의 변경을 최소화하면서 코드 부분을 변경할 수 있다는 것입니다.

따라서 건물의 전체 배경을 알 수는 없지만 인터페이스/공장 접근 방식을 사용합니다.

작은 응용 프로그램이나 프로토 타입에서 인터페이스가 바람직 할 경우/느낌이 들기 전까지는 종종 구체적인 클래스로 시작합니다. 인터페이스는 구축중인 앱의 규모에 꼭 필요한 것은 아닌 수준의 간접 참조를 도입 할 수 있습니다.

결과적으로 더 작은 응용 프로그램에서는 실제로 사용자 정의 인터페이스가 필요하지 않습니다. 많은 것들과 마찬가지로, 상황에 맞는 비용과 이익을 좌우해야합니다.

+0

감사합니다. 선언과 정의 사이에 명확한 경계를 제공하기 때문에이 솔루션을 사용하게되었습니다. 따라서 인터페이스를 사용할 때 인터페이스 헤더 파일 만 포함하고 구현을 포함하는 헤더 파일은 포함 할 필요가 없습니다. – Seth

1

"더 나은"어떤 의미로?

하나의 구체적인 클래스 만 가질 계획이라면 팩토리 메서드는별로 구입하지 않습니다. (그러나 다시 한번, 하나의 구체적인 클래스를 가질 계획이라면, 인터페이스 클래스가 정말로 필요합니까? COM을 사용한다면 예, 그렇습니다. 구체적인 클래스의 수를 지정하면보다 간단한 구현이 전체적으로 "더 나은"것일 수 있습니다.

그러나 많은 구체적인 클래스가있을 수 있으며 기본 클래스를 그 클래스에 단단히 연결하고 싶지 않으면 팩터 리 패턴이 유용 할 수 있습니다.

예,이 입니다. 기본 클래스가 파생 클래스가 기본 클래스에 등록 할 수있는 방법을 제공하는 경우 커플 링을 줄이는 데 도움이됩니다. 이것은 공장이 파생 된 클래스가 무엇인지, 그리고 그것들에 대한 컴파일 시간 정보를 필요로하지 않고 생성 방법을 알 수있게합니다.

+0

실제로 COM을 사용하고 있습니다. VCL GUI가있어서 Windows Explorer에서 드래그 앤 드롭해야합니다.그래서 내 인터페이스에서 IDropTarget을 상속하고 있으며이 인터페이스를 통해 핸들을 등록하기 위해 응용 프로그램에서 대상을 놓기를 원하는 구성 요소를 얻고 있습니다. 따라서 아마도 factory 메소드를 사용하는 것은 가치가 없을 것이며 위의 Micahel Safyan의 제안을 사용하는 것이 좋습니다. – Seth

0

더 일반적이며 이해하기 쉽기 때문에 첫 번째 옵션을 사용합니다. 그것은 당신에게 달려 있습니다.하지만 상용 응용 프로그램을 사용하고 있다면 동료들에게 무엇을 사용하는지 물어볼 것입니다.당신이 언급하지 않은 또 다른 대안이

4

: 즉

 
int main(int argc, char* argv[]) 
{ 
    //... 
    boost::shared_ptr<IInterface> test(new AImplementation); 
    //... 
    return 0; 
} 

, 하나는 정적 "생성"기능을 사용하지 않고 스마트 포인터를 사용할 수 있습니다. 스마트 포인터의 이점은 명백한 반면 "작성"기능은 코드 팽창을 추가하기 때문에이 방법을 선호합니다.

+2

구현이 숨겨져 있거나 동적으로로드되거나 (예 : AWindowsImplementation, AMacImplementation, ALinuxImplementation) 플랫폼에 종속되거나 구성 매개 변수의 수에 따라 달라지는 경우 구현을 작성해야합니다. 그러나, IMHO, 당신은 그것을 위해 별도의 Factory 클래스를 사용해야합니다. –

2

질문에 두 가지 개별적인 문제가 있습니다. 1. 생성 된 개체의 저장소를 관리하는 방법. 2. 개체를 만드는 방법.

파트 1은 간단합니다. std :: tr1 :: shared_ptr과 같은 스마트 포인터를 사용하면 그렇지 않으면 멋진 try/catch 논리가 필요한 메모리 누수를 방지 할 수 있습니다.

2 부는 더 복잡합니다.

메인()에서 원하는대로 main()을 작성할 수 없습니다. IInterface :: create()를 작성해야합니다. 그렇지 않으면 컴파일러가 create라는 글로벌 함수를 찾고 있기 때문입니다. 네가 원하는게 아니야. create()에 의해 반환 된 값으로 초기화 된 'std :: tr1 :: shared_ptr 테스트'가 원하는 것처럼 보일 수도 있지만 C++ 컴파일러가 작동하지 않는 것처럼 보일 수 있습니다.

새로운 AImplementation()을 사용하는 것보다 인터페이스에서 팩토리 메서드를 사용하는 것이 더 좋은 방법인지 여부는 상황에 도움이 될 수 있지만 투기 복잡성에주의해야합니다. 항상 AImplementation을 생성하고 결코 BImplementation 또는 CImplementation을 생성하지 않도록 인터페이스를 작성하므로 추가 복잡성이 무엇인지 파악하기 어렵습니다.

1

첫 번째 방법을 사용하십시오. 두 번째 옵션의 팩토리 메서드는 구체적인 클래스마다 구현해야하며 인터페이스에서 수행 할 수 없습니다. 즉, IInterface :: create()는 실제로 어떤 구체적인 클래스를 실제로 인스턴스화 할 것인지 전혀 모른다.

정적 메서드는 가상 일 수 없으며 구체적인 클래스에 정적이 아닌 create() 메서드를 구현해도이 경우에는 아무 것도 얻지 못했습니다.

팩토리 메소드가 유용하지만 실제로 사용하는 것은 아닙니다.

Effective C++에서 두 번째 옵션을 권장하는 항목은 무엇입니까? 나는 내 책을 보지 못한다. (두 번째 책도 없다.) 그것은 오해를 해결할 수 있습니다.

당신이 포인터를 사용 하시겠습니까 :

+1

Item 31, 제 3 에디션을 가지고 있습니다 – Seth

+0

저는 효과적인 C++을 쓸모가 없지만, OP는 추상적 팩토리 패턴을 참조하고 있다고 생각합니다. (나는 항상 과잉이라고 생각 했었지만 어쩌면 적절한시기 일 수도 있습니다.) 각 구체적인 클래스에 대해 팩토리를 구현해야하는지 여부는 다음과 같습니다. public 인스턴스가 아닌 하나의 정적 메소드를 호출하여 구체적인 인스턴스를 작성합니다. 파생 클래스는 스스로를 건설에 사용할 수 있도록 공장에 등록합니다. 팩토리가 선택하는 방법 ** 주어진 시간에 빌드 할 ** 파생 클래스는 구현에 따라 다릅니다. –

+0

하지만 create() 메소드에 관해서는 당신이 맞습니다. 책에서 실제로 테스트 (IInterface :: create()) – Seth

0

나는 거기에 아주 간단한 질문이 있습니까?

이 질문은 논리적이지는 않지만 Java 백그라운드에서 오는 사람들은 필요 이상으로 자주 새로운 것을 사용합니다. 귀하의 예제에서 스택에 변수를 작성하면 충분합니다.