PIMPL const正确性

0xb*_*00d 4 c++ pimpl-idiom

.H

public:
    void doStuff() const;
private:
    struct Private;
    Private * d;
Run Code Online (Sandbox Code Playgroud)

的.cpp

struct XX::Private
{
    int count;
}

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

你需要更好的解释吗?

更新:

我以为我会做一些不同的事情,需要对代码进行较少的更改.我做的:

.H

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

的.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;
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

.H

#include <PrivatePtr.h>

class DLLEXPORTMACROTHING myclass
{
    ...
    private:
        struct Private;
        PrivatePtr<Private> d;
};
Run Code Online (Sandbox Code Playgroud)

的.cpp

#include <PrivatePtr.cpp>

struct myclass::Private()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

但这会导致C4251"myclass :: d:class'PrivatePtr'需要让clas'myclass'的客户端使用dll-interface

等等,什么?我不希望任何人使用它,但内部的myclass ...安全忽略?我试着寻找答案,但没有一个案例接近我在这里的情况.在其他情况下,它似乎确实有点问题.

小智 7

您可以隐藏d在访问者函数后面,并基于此重载const.d然后写,而不是直接访问impl()->count = 2;.impl()会回来Private *,而impl() const会回来const Private *.

  • @justanothercoder将它重命名为`_d_dont_use_directly`并点击任何直接使用它的人.:)更严重的是,你可以使成员变量本身为`const Private*`,而在非const`insl()`函数中,使用`const_cast`.这应该可以防止意外误用.. (2认同)