Pimpl,私有类前向声明,范围解析运算符
Pimpl, private class forward declaration, scope resolution operator
考虑这两个使用 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();
}
问题:
为什么在 ClassB.h 中将前向声明和变量声明组合在一行上要求
ClassB_Impl
在 ClassB 中的私有类的实现中"无作用域".cpp?即在 ClassA 中.cpp私有类方法定义以
void ClassA::ClassA_Impl::foo() {...
但在 ClassB.cpp 中,私有类方法定义以
void ClassB_Impl::foo() {...
每种方法的含义是什么? 哪一个更好?
(针对加利克的回答的后续问题(
当您将类的前向声明和该类的变量声明组合在一个语句中时...
//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?
相关文章:
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- ::(范围解析运算符)前面没有任何东西
- 使用范围解析运算符时,在构造函数中调用虚拟方法是否安全?
- 迭代器的范围 TS 和 C++20 概念是否需要能够使用"运算符>"?
- 运算符重载中的范围运算符
- 重载运算符 [] 以接受范围
- 为什么按位运算符在使用与整数中提供的位数相同的位数计算可能的最大范围时会产生错误
- 为什么C++找不到布尔运算符,当有一个!范围内的运算符?
- 运算符>的范围
- 范围分辨率运算符在类型:: var的情况下返回什么
- 如何在C 中访问无范围分辨率运算符的标头构件类型
- 为什么我们要把 :: (范围重新定位运算符)放在迭代器之前
- 删除复制构造函数和运算符=类范围访问
- 为什么可以使用范围运算符和类 A 名称在类 B 中访问类 A(公共)中的枚举
- 友元运算符中的变量范围
- C++是否提供了一种在没有范围解析运算符的情况下访问类中的类的方法?
- 范围运算符需要查找 std 命名空间而不是提升
- 为什么使用范围运算符 (::)在C++类初始化之前
- C++范围运算符分组
- 派生列表中的C++范围运算符