3

考虑使用 Pimpl 习语的这两个类:

ClassA:Pimpl 类前向声明​​和变量声明在不同的行上

类A.h:

#include <memory>

class ClassA {
public:
    ClassA();
    ~ClassA();
    void SetValue( int value );
    int GetValue() const;

private:

    class ClassA_Impl;
    // ^^^^^^^^^^^^^^ class forward declaration on its own line

    std::unique_ptr<ClassA_Impl> m_pImpl;
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variable declaration on its own line

    //EDIT:
    //Even if we use a raw pointer instead of a smart pointer,
    //i.e. instead of declaring the smart pointer above, if we declare:
    ClassA_Impl *m_pImpl;
    //the situation in the *.cpp files and my questions (below) are the same.


};

A类.cpp:

#include "ClassA.h"

class ClassA::ClassA_Impl {
public:
    void SetValue( int value );
    int GetValue() const;
private:
    int value_;   
};

// Private class implementation
void
ClassA::ClassA_Impl::SetValue( int value ) {
    value_ = value;
}

int
ClassA::ClassA_Impl::GetValue() const {
    return value_;
}

// ClassA implementation
ClassA::ClassA() : m_pImpl( new ClassA_Impl() ) {}

ClassA::~ClassA() {}

void
ClassA::SetValue( int value ) {
    m_pImpl->SetValue( value );
}

int
ClassA::GetValue() const {
    return m_pImpl->GetValue();
}

ClassB:Pimpl 类前向声明​​和变量声明在一行

B类.h:

#include <memory>

class ClassB {
public:
    ClassB();
    ~ClassB();
    void SetValue( int value );
    int GetValue() const;

    private:
        std::unique_ptr<class ClassB_Impl> m_pImpl;
        //             ^^^^^^^^^^^^^^^^^^ class forward declaration
        //             combined with variable declaration on one line,
        //             in one shot.

        //EDIT:
        //Even if we use a raw pointer instead of a smart pointer,
        //i.e. instead of declaring the smart pointer above, if we declare:
        class ClassB_Impl *m_pImpl;
        //the situation in the *.cpp files and my questions (below) are the same.
};

B类.cpp:

#include "ClassB.h"

class ClassB_Impl {
public:
    void SetValue( int value );
    int GetValue() const;
private:
    int value_;
};

// Private class implementation
void
ClassB_Impl::SetValue( int value ) {
    value_ = value;
}

int
ClassB_Impl::GetValue() const {
    return value_;
}

// ClassB implementation
ClassB::ClassB() : m_pImpl( new ClassB_Impl() ) {}

ClassB::~ClassB() {}

void
ClassB::SetValue( int nValue ) {
    m_pImpl->SetValue( nValue );
}

int
ClassB::GetValue() const {
    return m_pImpl->GetValue();
}

问题:

  1. 为什么在 ClassB.h 中将前向声明和变量声明组合在一行中,在 ClassB.cppClassB_Impl中的私有类的实现中需要“无作用域”?

    即在 ClassA.cpp 中,私有类方法定义以

    void ClassA::ClassA_Impl::foo() {...
    

    但在 ClassB.cpp 中,私有类方法定义以

    void ClassB_Impl::foo() {...
    
  2. 每种方法的含义是什么?哪一个更好?

  3. 回应Galik回答的后续问题

    当您在一个语句中组合一个类的前向声明和该类的变量声明时......

    //one-liner
    class ClassB_Impl *m_pImpl;
    

    ...这个叫什么?这种组合语句有名称吗?由于这样的陈述,为什么不ClassB_Impl成为一个内部类?ClassB

    将此与...进行比较

    //two-liner
    class ClassA_Impl;
    ClassA_Impl *m_pImpl;
    

    ...在这种情况下ClassA_Impl 确实成为ClassA.

    为什么单行放入ClassB_Impl全局命名空间,而二行ClassA_Impl放入ClassA's 命名空间?为什么它们不同?

4

1 回答 1

1

为什么在 ClassB.h 中将前向声明和变量声明结合在一行中,要求 ClassB_Impl 在 ClassB.cpp 中的私有类的实现中是“无作用域的”?

因为在第一个示例中,您声明ClassA_Impl为.ClassA

当您ClassB_Impl在不属于. _ClassB

每种方法的含义是什么?哪一个更好?

这是一个见仁见智的问题。就我个人而言,我认为内部课程是混乱的,并且难以与很少的回报一起工作。

我的首选方法使用单独的接口类,这有助于减少您必须重新声明接口的次数。

请参阅: 是否可以在 C++ 中编写敏捷 Pimpl?

于 2016-02-08T06:35:52.283 回答