[英]How to omit private non-virtual methods from class definition?
Lets say I have something like the following: 可以说我有以下内容:
a.hpp: a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
}
a.cpp: a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
something_complicated& A::get_complicated() { return b_->x; }
Unfortunately, in this case, a.cpp will fall to compile because "get_complicated()" is not a method of A. 不幸的是,在这种情况下,a.cpp将无法编译,因为“ get_complicated()”不是A的方法。
So, we can try this: 因此,我们可以尝试这样:
a.hpp: a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
something_complicated& A::get_complicated();
}
But then a.hpp fails to compile because something_complicated isn't defined. 但是随后a.hpp无法编译,因为未定义something_complicated。
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out. 如果它是一个类,我们可以向前声明something_complicated,但是它可能是typedef,所以就可以了。
The only way I can think of doing this without making b_ public nor including something_complicated.hpp in a.hpp is the following: 我可以想到不公开b_或在a.hpp中不包含something_complicated.hpp的唯一方法是:
a.cpp: a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
#define get_complicated ((b_->x))
Surely I don't have to define a macro to get around this issue? 当然,我不必定义宏来解决此问题吗? Any alternatives?
有其他选择吗?
The easiest solution is probably to wrap a reference to the complicated type in a class, forward declare that in a.hpp
, and define it in something_complicated.hpp
. 最简单的解决方案可能是将对复杂类型的引用包装在类中,在
a.hpp
向前声明该a.hpp
,然后在something_complicated.hpp
定义它。
a.hpp: a.hpp:
class B;
class complicated_ref;
class A
{
public:
complicated_ref get_complicated();
private:
std::unique_ptr<B> b_;
};
something_complicated.hpp: something_complicated.hpp:
// ... complicated definitions ...
typedef whatever something_complicated;
struct complicated_ref
{
complicated_ref(something_complicated & thing) : ref(thing) {}
something_complicated & ref;
};
Now a.cpp
and anything that needs to use the complicated type must include it's header, but anything that just wants to use class A
does not need to. 现在,
a.cpp
和任何需要使用复杂类型的东西都必须包含其标头,但是任何只想使用class A
东西都不需要。
This is assuming that there's a good reason for some clients of A
to access the complicated thing, but for B
to be inaccessible to everyone. 这是假设有充分的理由让
A
某些客户访问复杂的事物,而B
却是每个人都无法访问的。 It would be simpler still to allow access to B
when required, and get to the complicated thing through that. 允许在需要时访问
B
并通过它来处理复杂的事情仍然会更简单。
Just avoid referring to something_complicated
in a.hpp
. 只要避免引用
a.hpp
something_complicated
a.hpp
。
One solution is to replace the member function get_complicated
with a free function, or a static method of another class. 一种解决方案是将成员函数
get_complicated
替换为自由函数或另一类的静态方法。
.h : .h :
class A_impl_base {
A_impl_base() {}
friend class A_impl; // all instances of A_impl_base are A_impl
}; // this stub class is the only wart the user sees
class A
{
private:
std::unique_ptr< A_impl_base > b_; // this is not a wart, it's a pimpl
friend class A_impl;
}
.cpp : .cpp :
class A_impl : A_impl_base {
static A_impl &get( A &obj ) { return * obj.b_; }
static A_impl const &get( A const &obj ) { return * obj.b_; }
};
What's wrong with: 有什么问题:
a.hpp: a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
public:
B& get_B();
}
If your clients want to get something complicated out of B, then let them #include <something_complicated.hpp>
. 如果您的客户希望从B中获得一些复杂的东西,请让他们
#include <something_complicated.hpp>
。
I am afraid there is a misunderstand on what belong to the class, and what does not. 恐怕对什么属于班级,什么不属于班级有误解。
Not all methods that act on the internals of the class should be class methods, after all, we have friend
functions already. 并不是所有作用于类内部的方法都应该是类方法,毕竟,我们已经有了
friend
函数。 I know that many people declare the helper methods as private functions, however doing so introduces needless dependencies (compile-time) and a visibility issue with friend
s. 我知道很多人将帮助程序方法声明为私有函数,但是这样做会引入不必要的依赖关系(编译时)以及与
friend
的可见性问题。
When dealing with PIMPL, I tend not to use private functions. 在处理PIMPL时,我倾向于不使用私有函数。 Instead, the choice is:
相反,选择是:
Impl
( B
in your case) a true class, with its own validation logic and true API Impl
(在您的情况下为B
)成为一个具有自己的验证逻辑和真实API的真实类 static
free functions (or functions declared in an anonymous namespace) static
自由函数(或在匿名名称空间中声明的函数) Both are good, and use whichever seems most appropriate. 两者都很好,可以使用最合适的方法。 Namely:
即:
It is deliberate on my part to search to have as few methods as possible, because those are the only ones that can screw up my class invariants, and the less they are the more confident I can be that the invariants will be maintained. 我有意搜索尽可能少的方法,因为那些是唯一可以使我的类不变式搞砸的方法,而它们越少,我就越有信心要保持不变式。
In your case, it's up to you to decide which approach suits you best. 在您的情况下,由您决定哪种方法最适合您。
In Action: 在行动中:
a.cpp a.cpp
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
static something_complicated& get_complicated(B& b) { return b_.x; }
// or anonymous namespace instead
namespace {
something_complicated& get_complicated(B& b) { return b_.x; }
}
Not so different from what you had, eh ? 与您所拥有的没有什么不同,是吗?
Note: I prefer static functions to anonymous namespaces because it's more obvious when reading. 注意:与匿名名称空间相比,我更喜欢静态函数,因为在阅读时它更明显。 Namespaces introduce scopes, and scope are not glanced easily when sifting through a file.
命名空间引入了作用域,并且在文件中筛选时不容易浏览范围。 Your mileage may vary, both offer identical functionality (for functions).
您的里程可能会有所不同,两者都提供相同的功能(针对功能)。
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out.
如果它是一个类,我们可以向前声明something_complicated,但是它可能是typedef,所以就可以了。
This is exactly what you have to do. 这正是您要做的。 And I don't see how being a typedef rules out a forward declaration.
而且我不认为成为typedef会排除正向声明。
如果您控制something_complicated.hpp
,则可以执行标准库的操作:创建一个具有适当前向声明(包括可能为typedef或不为typedef的类型)的something_complicated_fwd.hpp
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.