Вопрос

My class uses the PImpl idiom and looks something like this:

// In LongDescriptiveClassName.hpp

class LongDescriptiveClassName
{
public:
    // Stuff...

private:
    struct LongDescriptiveClassNameData;

    LongDescriptiveClassNameData &Data;
};

In the .cpp file, I declare/define the private struct:

// In LongDescriptiveClassName.cpp

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

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

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

This is painful for me to read. Is there a way that I can abbreviate the names leading up to the private methods?

My understanding is that I can't typedef it in the .cpp file because the PImpl struct is private. Would it be an evil to use #define?

#define ShortName LongDescriptiveClassName::LongDescriptiveClassNameData

struct ShortName
{
    // ...
};

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

This .cpp file is the only source file that would need to abbreviate it, and then only for method definitions. What do you recommend?

Это было полезно?

Решение

The class name is already a namespace, so there's no reason to give the impl such a long name:

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...
}

It works just fine.

Incidentally, your code is not an example of the pimpl idiom. The "p" in "pimpl" means "pointer", and this is important. A reference means that the object does not own its implementation.

It's not necessarily wrong; there are sometimes good reasons to wrap a reference in a class, but it's not the pimpl idiom.

Другие советы

I'm not completely sure to understand your problem but it seems that a proper use of the using keyword should help a lot. Isn't

using ShortName = LongDescriptiveClassName::LongDescriptiveClassNameData

what you are looking for ?

Note this only work is LongDescriptiveClassNameData is a type not a data.

While @Pseudonym's solution is absolutely fine, I prefer to use names with initial upper case only for types, so I think I'd just do:

class LongDescriptiveClassName {
private:
    struct Data;

    Data &data;
};

I like to call it Impl, or Detail (though the latter is common as a namespace detail, also).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top