Pimpl,私有类前向声明,范围解析运算符

Pimpl, private class forward declaration, scope resolution operator

本文关键字:范围 运算符 声明 Pimpl      更新时间:2023-10-16

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

A类: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();
}

B类:Pimpl 类前向声明和变量声明在一行上

ClassB.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_Impl在 ClassB 中的私有类的实现中"无作用域".cpp?

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

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

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

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

  3. (针对加利克的回答的后续问题(

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

    //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的命名空间? 它们为什么不同?

为什么将前向声明和变量声明合并到 ClassB.h 中的一行要求ClassB_Impl在 在 B类.cpp 中实现私有类?

因为在第一个示例中,您将ClassA_Impl声明为 ClassA 的内部

当您在不属于ClassB模板参数中声明ClassB_Impl它时。

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

这是一个见仁见智的问题。就我个人而言,我认为内部课程很混乱,很难合作,回报却很少。

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

参见:是否可以用 c++ 编写敏捷 Pimpl?