Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top