2014-06-20 2 views
3

현재 복사 생성자 및 소멸자를 선언하고 pimpl 객체에 대한 참조 카운트를 유지하는 구조를 가지고 있습니다. 이렇게하면이 구조체를 값으로 전달할 수 있습니다. 필자는 이전 C++ 플레버를 사용하는 코드에서 사용해야하는 라이브러리의 일부이기 때문에 POD 인터페이스가 필요하기 때문에 리팩토링해야합니다. 이 때문에 복사 생성자와 desctructor를 모두 제거해야합니다. 나는 이것을 제거한 후에이 "가치있는 패스", 다중 소유권 메커니즘을 어떻게 유지할 수 있는지 알 수 없다. 공유 포인터는 라이브러리의 사용자 관점에서 POD로 볼 필요가있는 다른 클래스의 메소드에 대한 매개 변수로 구조가 사용되기 때문에 옵션이 아닙니다. 상기 변수가 주 라이브러리 내의 장시간 유지할 수있다이 점에서POD 인터페이스를 노출하는 참조 계산 구조

MainLibrary ml; 
{ 
    Foo a; 
    ml.doSomething(a); 
} 

: 같이

struct Foo { 
    Foo(const Foo&); 
    const Foo& operator=(const Foo&); 
    ~ Foo(); 
private: 
    void* pimpl; 
}; 

struct MainLibrary { 
    void DoSomething(Foo param); 
} 

사용자 이제 코드이다. 효율을 위해 Foo의 내부는 매번 깊은 복사가 불가능하므로 Pimpl 구현시 Foo의 인스턴스가 복사 될 때마다 증가하는 참조 카운터를 유지하고 Foo의 인스턴스가 삭제 될 때마다 감소됩니다.

+0

"오전 당신이 또는 유사한"C로 ++ 코드를 C를 노출 "를 검색하면 당신은 ....

foo03.h을 예를 많이 찾을 수 있습니다 오래된 C + + 풍미 "귀하의 복사본 생성자, 소멸자를 호출을 지원하지 않습니다? 어떻게 C++ 일 수 있습니까? "이 객체를 추적 할 수는 없지만 모두 완료되면 다른 객체가 삭제되어야합니다."- 소멸자가 없으면 가비지 수집기 만 연결할 수 있습니다. –

+0

아니요. 문제는 라이브러리 전반에 걸쳐 C++ 11을 사용하고 있으며 C++ 11 플래그없이 컴파일 된 코드를 사용하여 링크 할 수 있어야합니다 ... POD 유형이 아닌 경우 이름이 잘못되었을 때 오류가 발생합니다. –

+1

당신의 질문에서 빠져 나갈 꽤 큰 통찰력입니다. 이 경우에는 "glue"데이터 및/또는 함수를 사용하여 현재 디자인을 사용할 수 있다고 확신 할 수 있습니다. 아마도 외부 C "비회원이되어 어느 쪽에서도 호출 할 수 있고 C + +11 코드 레지스터 콜백을 사용하여 pre-C++ 11 측에서 필요한 기능을 찾을 수 있습니다. 또한 컴파일러 워드 프로세서가 이름 차이를 제어 할 수 있는지 확인하십시오 .... –

답변

1

댓글이 너무 많아서 아래와 같이 표시됩니다. 클라이언트는 foo03.h를 포함하며 사용법은 영향을받지 않습니다. C++ 11 구현은 "C"계층을 통해 호출됩니다.

extern "C" 
{ 
    void* foo_constructor(); 
    void* foo_constructor2(void* rhs); 
    void foo_assign(void* lhs, void* rhs); 
    void foo_destructor(void* p_this); 
} 

struct Foo { 
    Foo() { p_ = foo_constructor(); } 
    Foo(const Foo& rhs) { p_ = foo_constructor2(rhs.p_); } 
    const Foo& operator=(const Foo& rhs) { foo_assign(p_, rhs.p_); return *this; } 
    ~Foo() { foo_destructor(p_); } 
    private: 
    void* p_; 
}; 

foo11.h :

// up to you whether you call this Foo (relying on mangling differences to avoid conflicts when 
// linking with C++03 objects), FooImpl, put it in a namespace ala Impl::Foo etc.. 
struct FooImpl { 
    FooImpl() { ... } 
    FooImpl(const FooImpl&) { ... } 
    const FooImpl& operator=(const FooImpl& rhs) { ... } 
    ~FooImpl() { ... } 
}; 

extern "C" 
{ 
    void* foo_constructor() { return new FooImpl(); } 
    void* foo_constructor2(void* rhs) { return new FooImpl(*(FooImpl*)rhs); } 
    void foo_assign(void* lhs, void* rhs) { *(FooImpl*)lhs = *(FooImpl*)rhs; } 
    void foo_destructor(void* p_this) { delete (FooImpl*)p_this; } 
} 
+0

대단히 감사합니다, 굉장한! –

+0

@AlexDarsonik 환영합니다. 원활하게 진행되기를 바랍니다. –

+0

필자가 알고있는 한, C는 함수 오버로드가 없으므로 (그것들을 구별하기 위해 이름을 바꾸는 이름이 없다), 두 foo_constructor가 충돌 할 것이다. – magras