如何合理设计图书馆的外部访问而不干扰其内部访问
How to properly design library external access without mess up its internal access?
我正在尝试设计一个库,只向调用者开放几个接口,而不会弄乱自己的内部访问控制。正确的做法是什么?
例如,下面是库:
namespace ControlledLib {
class ThinkTrack1 {
friend class DeepThought;
friend class ThinkTrack2;
private:
int ResultA() { return 6; }
int ResultB() { return 5; }
};
class ThinkTrack2 {
friend class DeepThought;
private:
int ResultC() { ThinkTrack1 tt1; return tt1.ResultB() + 2; }
};
class DeepThought {
friend int DeepThoughtAnswers();
private:
int Answers() {
ThinkTrack1 tt1;
ThinkTrack2 tt2;
return tt1.ResultA() * tt2.ResultC();
}
int CreateWorld() {
return 7;
}
};
int DeepThoughtAnswers() { DeepThought dt; return dt.Answers(); }
}
,它可以通过
调用#include "ControlledLib.h"
int i = ControlledLib::DeepThoughtAnswers();
实际的答案是由class DeepThought
的函数Answers()
给出的,然而,为了使外部调用者只能访问一个Answers()
,我必须使class DeepThought
的函数私有,并创建一个全局函数DeepThoughtAnswers()
作为入口点,它调用class DeepThought
来获得答案,然后class DeepThought
必须将DeepThoughtAnswers()
定义为朋友函数。
才刚刚开始。因为class DeepThought
实际上调用class ThinkTrack1
和class ThinkTrack2
, class ThinkTrack2
调用class ThinkTrack1
等等…为了使所有这些外部调用者无法访问,所有这些函数都被设置为private,并且我必须定义许多friendship。最重要的是,所有这些都搞乱了内部访问控制!
有什么更好的方法吗?
在设计界面时,您可以从中选择一些选项。第一种方法是只定义一个导出一组函数的C接口。这些函数在内部调用你的类,这些类隐藏在这一层中。
<ControlledLib.h>
extern "C" int DeepThoughAnswers();
</ControlledLib.h>
在源文件中,你有这个函数的实现:
<ControlledLib.cpp>
#include "DeepThought.h"
#include "ThinkTrack1.h"
#include "ThinkTrack2.h"
int DeepThoughAnswers()
{
DeepThought dt;
return dt.Answers();
}
</ControlledLib.cpp>
您在此源代码中包含的文件然后使用不含friend
的可见性,并且您只发布结果库和ControlledLib.h
文件。
另一种方法是使用c++接口隐藏实现细节。接口来了:
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
};
</ControlledLib.h>
那么你就有了这个接口的实现,它看起来像这样:
<MyControlledLib.h>
class MyControlledLib : public ControlledLib
{
public:
virtual int DeepThoughAnswers();
void someOtherFunction(); //<-- not visible to the 'outside'
};
</MyControlledLib.h>
此外,您添加了一个工厂,允许客户端实例化您的库。
<ControlledLib.h>
#include "ControlledLib.h"
class MyControlledLibFactory
{
public:
static MyControlledLib* create();
};
</MyControlledLib.h>
对于客户端,您只发送工厂和接口,其他一切都是隐藏的。到目前为止,您的接口只使用基本类型,这意味着您不必导出任何其他内容。如果希望在接口中使用类,还需要导出这些类以供使用。
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
virtual ComplexAnswer* DeepThoughAnswersAreComplex() = 0; //<-- ComplexAnswer header needs to be supplied too.
};
</ControlledLib.h>
我建议你使用更多受保护的关键字,减少朋友关键字的使用,重新设计界面,因为它看起来很乱。实现和接口的桥接设计模式将是很好的,您可以将实现隐藏为库,并将接口仅作为头文件分发。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 从C++dll访问C#中的一行主要参数
- 概念TS检查忽略私有访问修饰符
- 访问被拒绝后,c++中的故障保护代码
- 在c++中访问int到类对象的映射时出错
- 我想访问std::unique_ptr中的一个特定元素
- 为什么示例代码访问IUnknown中已删除的内存
- C++:无法访问声明的受保护成员
- 如何合理设计图书馆的外部访问而不干扰其内部访问
- 通过getter访问的c++类成员会产生垃圾,直接访问可以,但std::cout会干扰