2013-11-04 14 views
3

.HPIMPL의 CONST의 정확성

public: 
    void doStuff() const; 
private: 
    struct Private; 
    Private * d; 

통화 당

struct XX::Private 
{ 
    int count; 
} 

void XX::doStuff() const 
{ 
    d->count = 2; // I want an error here!! 
} 

당신은 furher 설명이 필요합니까?

업데이트 : 내가 코드에 덜 변경해야 조금 다른 뭔가를 할 거라고 생각

.

.H

template <class TPriv> 
class PrivatePtr 
{ 
    public: 
     ... 
     TPriv * const operator->(); 
     TPriv const * const operator->() const; 
     ... 
    private: 
     TPriv * m_priv; 
}; 

.CPP이 같은

... 

template <class TPriv> 
TPriv * const PrivatePtr<TPriv>::operator->() 
{ 
    return m_priv; 
} 

template <class TPriv> 
TPriv const * const PrivatePtr<TPriv>::operator->() const 
{ 
    return m_priv; 
} 

그리고 그것을 사용 :

.H

#include <PrivatePtr.h> 

class DLLEXPORTMACROTHING myclass 
{ 
    ... 
    private: 
     struct Private; 
     PrivatePtr<Private> d; 
}; 

통화 당

난이 만든
#include <PrivatePtr.cpp> 

struct myclass::Private() 
{ 
    ... 
} 

그러나 이것은 "C4251 원인 MyClass의 :: D : 클래스 'PrivatePtr은'DLL 인터페이스는 CLA를 'MyClass에'

대기, 어떤 클라이언트가 사용되어야 할 필요가 있겠습니까? 내부적으로 myclass가 아닌 다른 누구에게도 사용되는 것을 원하지는 않습니다 ... 무시해도 안전합니까? 나는 대답을 찾고자했지만 어떤 경우도 내가 여기있는 것에 가깝지 않았다. 다른 경우에는 상당히 문제가있는 것으로 보입니다.

+2

나는 당신의 문제에 대한 설명을 매우 좋아합니다. –

+1

상수 포인터는 상수에 대한 포인터와 다릅니다. transitive constence를 적용하려면 자체 래퍼를 작성해야합니다. –

답변

2

.H

template <class TPriv> 
class PrivatePtr 
{ 
    public: 
     ... 
     TPriv * const operator->(); 
     TPriv const * const operator->() const; 
     ... 
    private: 
     TPriv * m_priv; 
}; 

통화 당

... 

template <class TPriv> 
TPriv * const PrivatePtr<TPriv>::operator->() 
{ 
    return m_priv; 
} 

template <class TPriv> 
TPriv const * const PrivatePtr<TPriv>::operator->() const 
{ 
    return m_priv; 
} 

그리고 다음과 같이 사용 :

.H

#include <PrivatePtr.h> 

class DLLEXPORTMACROTHING myclass 
{ 
    ... 
    private: 
     struct Private; 
     PrivatePtr<Private> d; 
}; 

통화 당

#include <PrivatePtr.cpp> 

struct myclass::Private() 
{ 
    ... 
} 
7

접근 자 기능 뒤에 d을 숨기고 const을 기반으로 오버로드 할 수 있습니다. d에 직접 액세스하는 대신 impl()->count = 2;을 작성하십시오. impl()Private *을 반환하지만 impl() constconst Private *을 반환합니다.

+0

거의 내가 원하는. 여전히 멤버 변수에 대한 직접 액세스를 차단해야합니다. 그래도 좋은 제안! – 0xbaadf00d

+2

@justanothercoder '_d_dont_use_directly'로 이름을 바꾸고 막대기로 직접 사용하는 사람을 치십시오.:) 더 심각하게, 멤버 변수 자체를'const Private *'로 만들 수 있고, const가 아닌'impl()'함수에서'const_cast'를 사용할 수 있습니다. 우발적 인 오용을 방지해야합니다. – hvd

+0

복사 생성자를 삭제해야합니다. 그렇지 않으면 const XX를 비 const로 복사 한 다음 비 const 멤버 functoins를 사용할 수 있습니다. –

0

전체 클래스를 내보내기 용으로 표시하는 대신 dll을 통해 사용하려는 기능 만 표시하십시오.

class myclass 
{ 
public: 
    DLLEXPORTMACROTHING myclass(); 
    DLLEXPORTMACROTHING ~myclass(); 

    DLLEXPORTMACROTHING void myfunction(); 
... 
private: 
    struct Private; 
    PrivatePtr<Private> d; 
}; 
+0

죄송하지만 답변과 관련이 없습니다. 왜 내가 매크로를 넣었는지조차 모르겠다. 어쩌면 어떤 점이 있었는지도 모르겠지만, 솔직히 더 이상 기억할 수 없다. – 0xbaadf00d

+0

원래 질문에 대한 대답이 아니라는 것을 깨달았지만 이것을 추가하는 것이 좋을 것이라고 생각했습니다. 아마도 주석으로 더 좋았을 것입니다 ... – Lambage