- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
与特定任务相关的类依赖于特定的第 3 方库来执行此任务(比方说 JSON 序列化)。库的使用对客户端应该是透明的,并且类的公共(public)接口(interface)中没有引用任何第 3 方代码类或数据类型。
在引入私有(private)方法之前,我可以将所需的 #include
添加到 .cpp 文件中。但是,现在我根据第 3 方代码声明了一个私有(private)方法,我必须将一些#includes 提取到头文件中,这反过来导致将相应的头文件包含在所有其他文件中,包括我的类的头文件。
我正在考虑使用函数而不是私有(private)方法,这样我就不必在 header 中声明函数。当然,我必须将对我正在使用的字段的引用传递给这些函数。这是解决此问题的合理方法,还是在使用私有(private)方法时有实现这种封装的最佳实践?
最佳答案
假设你必须添加那些私有(private)方法
Json::Node AsJson() const;
std::string Serialize(const Json::Node& root) const;
Json::Node Unserialize(const std::string& document) const;
void InitFrom(const Json::Node&);
前向声明
假设Json
是一个namespace
,在header中你只需要前向声明
namespace Json
{
class Node;
}
代替
#include <3rdLibrary/Json.hpp>
如果 Json
是一个类并且 Json::Node
是一个内部类,则不能使用前向声明
免费功能如果该函数不需要私有(private)访问(以及其他一些不需要虚拟的东西),您可以创建自由函数(在未命名的命名空间或 static
中)
所以在 header 和 cpp 中没有任何内容:
#include <3rdLibrary/JsonCpp.hpp>
namespace {
Json::Node AsJson(const MyClass& myclass) {/**/}
std::string Serialize(const MyClass& myclass, const Json::Node& root) {/**/}
Json::Node Unserialize(const MyClass& myclass, const std::string& document) {/**/}
void InitFrom(MyClass& myclass, const Json::Node&){/**/}
}
MyClass::foo()
{
Serialize(*this, AsJson(*this));
/**/
}
PIMPL 成语Pimpl 习语是另一种选择
// header.hpp
class MyClass
{
public:
~MyClass();
MyClass(const MyClass&); // = delete ?
MyClass& operator =(const MyClass&); // = delete ?
MyClass(MyClass&&); // = delete ?
MyClass& operator =(MyClass&&); // = delete ?
// previous public methods.
private:
struct Pimpl;
std::unique_ptr<Pimpl> pimpl;
};
源码
// MyClass.cpp
struct Pimpl
{
// What you should have done in MyClass
};
MyClass::~MyClass() = default; // which destroys Pimpl and should know Pimpl definition
// that's why it is not in header
ReturnType MyClass::publicMethod(Args args) {return pimpl->publicMethod(args);} // Same for all public methods.
注意:使用 pimpl idiom 可能只隐藏部分实现
界面
最后,类似于 pimpl 习语,你可以使用接口(interface)
// IMyClass.hpp
class IMyClass
{
public:
virtual ~IMyClass() = default;
IMyClass(const IMyClass&); // = delete ?
IMyClass& operator =(const IMyClass&); // = delete ?
IMyClass(IMyClass&&); // = delete ?
IMyClass& operator =(IMyClass&&); // = delete ?
// previous public methods but virtual.
};
std::unique_ptr<IMyClass> makeMyClass(Args);
并正常实现MyClass
(使用override
)(它的头文件只被它的cpp文件使用)
并实现
std::unique_ptr<IMyClass> makeMyClass(Args args) { return std::make_unique<MyClass>(args); }
注意:可以通过接口(interface)只暴露一部分(只隐藏一部分代码)。
关于c++ - 避免在头文件中包含私有(private)方法所需的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31723990/
我有一个依赖于包 B 的包 A。当包 A 中的代码运行并访问包 B 中的类时,包 B 的状态将被解析 (4),而不是 Activity (32) 和包 B 的激活器也没跑好。我认为 bundle B
这个问题在这里已经有了答案: How to remove the space between inline/inline-block elements? (41 个回答) 关闭 7 年前。
我正在尝试使用 Java OpenAL 库。我在导入名为 libsoft_oal.so 的 native 库时遇到问题。 Java OpenAL 依赖于 OpenAL 软实现。我尝试根据他们在 git
我正在尝试启动我的应用程序。是一个 unicorn +工头+sinatra的应用。 这是我的 config.ru 文件: require "rubygems" require "sinatra" Bu
我有一个下拉列表,其中包含一些从数据库表中检索的值,我想要的是当单击按钮时它应该只获得选项标签的中间值,但只有那些类名为“get_this”的选项标签并离开那些选项,如果他们没有这个类 预期输出:值
我有一个index.php文件,需要一个通用的head.php文件,head.php文件中有几个Javascript文件,当这样尝试时,代码在源代码中看起来很好,但文件却不是实际上对文档做任何事情。
有人能帮帮我吗? 我已经像这样运行了 imsmod: $ insmod /data/mm/mmdev.ko epoll_rate=100 但是我得到一个错误: insmod: init_module
是否有键盘快捷键或插件可以在 Notepad++ 中打开 PHP 所需或包含的文件?我知道,在 Dreamweaver 中,执行此操作的命令是 Ctrl+D,但我似乎无法在 Notepad++ 中找到
我已经用 js 设置了一个显示/隐藏 div,但我很难弄清楚如何一次显示一个 div。目前发生的情况是,除非我再次单击原始链接来关闭该 div,否则每个 div 都会显示。 http://www.li
当我尝试将未分配的辅助分片分配给节点时出现错误。 { "error": { "root_cause": [ { "type": "remote_transpor
我正在构建一个 C++ 应用程序,使用 Netbeans 6.9 作为我的 IDE。我有一个 C++ 库,它是一个纯 C 库的包装器。 我已将文件正确添加到项目中(使用添加库文件选项)。这是 g++
我是一名优秀的程序员,十分优秀!