【问题标题】:Private class name abbreviation techniques?私有类名缩写技术?
【发布时间】:2014-02-03 22:55:24
【问题描述】:

我的班级使用 PImpl 习语,看起来像这样:

// In LongDescriptiveClassName.hpp

class LongDescriptiveClassName
{
public:
    // Stuff...

private:
    struct LongDescriptiveClassNameData;

    LongDescriptiveClassNameData &Data;
};

在 .cpp 文件中,我声明/定义私有结构:

// In LongDescriptiveClassName.cpp

struct LongDescriptiveClassName::LongDescriptiveClassNameData
{
    void PrivateMethod1();
    void PrivateMethod2();
    // and so on...
};

void LongDescriptiveClassName::LongDescriptiveClassNameData::PrivateMethod1()
{
    // Stuff...
}

void LongDescriptiveClassName::LongDescriptiveClassNameData::PrivateMethod2()
{
    // Stuff...
}

这让我读起来很痛苦。 有没有办法可以缩写导致私有方法的名称?

我的理解是我不能在 .cpp 文件中 typedef 它,因为 PImpl 结构是私有的。使用#define会不会是一种邪恶?

#define ShortName LongDescriptiveClassName::LongDescriptiveClassNameData

struct ShortName
{
    // ...
};

void ShortName::PrivateMethod1()
// ...

这个 .cpp 文件是唯一需要缩写它的源文件,并且仅用于方法定义。你有什么推荐的?

【问题讨论】:

  • 不要使用LongDescriptiveClassNameData,而是使用ShortNameData。矮得多。如果您担心冲突,为什么不使用命名空间

标签: c++ class typedef private c-preprocessor


【解决方案1】:

类名已经是一个命名空间,所以没有理由给 impl 起这么长的名字:

class LongDescriptiveClassName
{
public:
    // Stuff...

private:
    struct Impl;

    // shared_ptr is also an option if that's
    // the semantics you want.    
    std::unique_ptr<Impl> Data;
};

// and off in the implementation, we have...
struct LongDescriptiveClassName::Impl
{
    void PrivateMethod1();
    void PrivateMethod2();
    // and so on...
};

void LongDescriptiveClassName::Impl::PrivateMethod1()
{
    // Stuff...
}

效果很好。

顺便说一句,您的代码不是 pimpl 习惯用法的示例。 “pimpl”中的“p”表示“指针”,这很重要。引用意味着对象不拥有它的实现。

不一定是错的;有时有充分的理由将引用包装在一个类中,但这不是 pimpl 习惯用法。

【讨论】:

  • 这很好,我想实现不需要这么长的名字。但是,如果我确实想进一步缩短名称以便仅在这个 .cpp 文件中使用,那么使用 #define 指令有什么危害?哦,我以为“p”代表“私人”。感谢您的信息。
  • 在这种情况下不使用#define 的唯一原因是,如果可能且合理的话,总是要避免使用C 风格的宏。宏颠覆了 C++ 类型系统,而 C++ 类型系统通常是你的朋友。
【解决方案2】:

我不能完全确定理解您的问题,但似乎正确使用 using 关键字应该会有很大帮助。不是

using ShortName = LongDescriptiveClassName::LongDescriptiveClassNameData

你在找什么?

请注意,这唯一的工作是 LongDescriptiveClassNameData 是类型而不是数据。

【讨论】:

  • 他说为什么不能这样做:LongDescriptiveClassNameData 是私有的。
【解决方案3】:

虽然@Pseudonym 的解决方案绝对没问题,但我更喜欢仅对类型使用首字母大写的名称,所以我想我会这样做:

class LongDescriptiveClassName {
private:
    struct Data;

    Data &data;
};

【讨论】:

  • 我通常不将我的 impl 称为“数据”,因为我也经常将成员函数放在那里。您想要隐藏的通常不仅仅是私人数据,还有私人行为。当然,您的里程可能会有所不同。
  • 我只是重用了原来的名字。我只会考虑 Data 适用于表示持久状态或类似内容的一堆属性
【解决方案4】:

我喜欢称它为ImplDetail(尽管后者也常见为namespace detail)。

【讨论】: