- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在分析 C++ 中的 API 设计问题,以及在将接口(interface)与实现分离时如何解决语言中的一个大漏洞。
我是一个纯粹主义者,坚信将系统的公共(public)接口(interface)与有关其实现的任何信息巧妙地分开。我每天都在一个巨大的代码库上工作,它不仅构建起来真的很慢,主要是因为头文件拉动了大量其他头文件,而且作为客户端也非常难以挖掘某些东西的作用,因为接口(interface)包含各种供公共(public)、内部和私有(private)使用的功能。
我的图书馆分为几层,每一层都使用其他层。向客户公开每个级别是一种设计选择,这样他们就可以通过使用较低级别的实体来扩展高级实体的功能,而无需 fork 我的存储库。
现在问题来了。在考虑了很长时间如何做到这一点之后,我得出的结论是,在 C++ 中几乎没有办法以满足所有 满足以下要求:
它不需要任何代码重复/冗余。原因:它不可扩展,虽然它对一些类型没问题,但它很快就会变成很多实际代码库的代码。代码库中的每一行都有维护成本,我更愿意花在有意义的代码行上。
零开销。原因:我不想为在编译时(或至少应该!)众所周知的东西支付任何性能。
这不是黑客攻击。原因:可读性、可维护性,而且因为它太丑了。
据我所知,这也是我的问题所在,在 C++ 中,有三种方法完全从类的公共(public)接口(interface)中隐藏类的实现。
C 在这里获胜。为您的实体定义一个不透明的句柄和一堆将该句柄作为第一个参数的函数很好地满足了所有要求,但这不是惯用的 C++。我知道有人可能会说“在编写 C++ 时只使用 C 风格”,但它没有回答这个问题,因为我们正在谈论一个惯用 C++ 解决方案。
最佳答案
Defining an opaque handle to your entity and a bunch of function that take that handle as the first argument beautifully satisfies all requirements, but it is not idiomatic C++.
您仍然可以将它封装在一个类中。不透明句柄将是该类的唯一私有(private)数据成员,它的实现不会以任何方式公开。在实现方面,它只是一个指向私有(private)数据结构的指针,由类的成员函数取消引用。这仍然是对 C 解决方案的一个小改进,因为所有相关数据和函数都将封装在一个类中,这使得客户端无需跟踪句柄并将其传递给每个函数。
是的,我想取消对指针的引用会引入一些微不足道的开销,但 C 解决方案也会有同样的问题。
不需要重复代码,虽然可以说它被认为是 hack(或者至少是不优雅的 C++ 设计),但它肯定不会比用 C 实现的相同方法更 hack。唯一的区别是 C 程序员对什么是“hack”的阈值较低,因为他们的语言表达设计的方式较少。
我正在考虑的设计草图(与 PIMPL 基本相同,但只有数据成员不透明):
// In a header file:
class DrawingPen
{
public:
DrawingPen(...); // ctor
~DrawingPen(); // dtor
void SetThickness(int thickness);
// ...and other member functions
private:
void *pPen; // opaque handle to private data
};
// In an implementation file:
namespace {
struct DrawingPenData
{
int thickness;
int red;
int green;
int blue;
// ... whatever else you need to describe the object or track its state
};
}
// Definitions of the ctor, dtor, member functions, etc.
// For instance:
void DrawingPen::SetThickness(int thickness)
{
// Get the object data through the handle.
DrawingPenData *pData = reinterpret_cast<DrawingPenData*>(this->pPen);
// Update the thickness.
pData->thickness = thickness;
}
如果您需要在 DrawingPen
上工作的私有(private)函数,但您不想在 DrawingPen
header 中公开,您只需将它们放在同一个匿名中实现文件中的命名空间,接受对类对象的引用。
关于c++ - C/C++ API设计困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35669729/
我正在使用 OneWayToSource绑定(bind),它似乎总是将我的源属性设置为空。为什么呢?这给我带来了麻烦,因为我需要源属性中目标属性的值而不是空值。 这是我的代码: MyViewModel
我有一个实例变量属性,它被声明和实例化,如下所示: $self->{properties}{$key1} = $value; 我的理解是这将声明属性字段,并将其设置为包含一个键值对的哈希原语。 我正
我正在尝试检查给定的数字是否是质数。首先采用试分割法。但该程序的行为很奇怪。这是我使用的。 int no; no = Integer.parseInt(jTextField1.getText());
我正在使用 NSUserDefaults使一个对象在多个 UIViewController 之间保持同步UITabbarController 中使用的 s .为此,我正在实现以下 - (void)vi
考虑以下 Java 方法: public Boolean compare(String val1, String val2) { return val1.length() > 0 && val
我有一个问题...假设我有一个包含城市名称的表。像这样: id name 1 Los Angeles 2 Madrid 我有一张用户表: uid username locationid
我无法理解这个问题。该代码非常基本,但它的行为却出乎意料。该代码是例程的简化版本,用于从每日数据库中提取每月第 15 天的数据并将其保存到单独的文件中。哪里有问题 ?第一个 cout 打印输入外部 i
我在 中使用大背景标签,我想制作一个宽度为 960px 的容器 div。我希望容器 div 位于从顶部向下 15px 的位置,我想我必须使用 position:absolute。我的困境是;容器内的
我遇到了一个难题。我有一个 hashedX 字段,它是一个散列值/加盐值,按照惯例,加盐值保存在 mysql 数据库的同一行中。 hashedX saltX ------ ---
类 java.io.Reader 和 java.io.InputStreamReader 都有具有完全相同签名的读取方法 public int read(char[] charbuf, int off
我有一个包含多个 C# 项目的 C# 解决方案。我打算在其中添加日志记录。此日志记录应该在所有项目中可用,并且最好使用带有滚动文件日志的 log4Net。 在上述前提下,我可以想到两种方法。 在解决方
我开始学习Python,目前我非常喜欢它。但是,如果你能帮我回答几个问题,这些问题一直困扰着我,我找不到任何明确的答案: 就语言兼容性而言,Python 的 C 实现(来自 python.org 的主
我正在尝试使用 AVAssetWriter 将 CGImages 写入文件以从图像创建视频。 我已经让它在模拟器上以三种不同的方式成功运行,但在运行 iOS 4.3 的 iPhone 4 上,每种方法
我需要对一个想法进行建模,可以将其分解并考虑如下: 图书详细信息 图书价格 这里的问题是您可以为书籍设置许多价格,并且这些价格可能会发生变化。这是一个例子 图书详细信息: --------------
我有一个表,其中的行包含名为 MySubId 的列。此列中的值可以重复。我想找到 MySubId 值和出现次数最多的 MySubId 值的行数。 我有以下查询: SELECT MySubId, COU
我有两个具有多对多关系的类,因此我在它们之间创建了一个联接表(一个非常经典的示例!) 在java+hibernate中我想知道哪种方式更好?使用hibernate多对多注释在这两个类之间有多对多关系吗
我正在尝试创建一个 Android 应用程序来完成以下任务:它通过短信向一组收件人(存储在数组中的数字)发送初始调查问题。然后,对于收到的每个响应,它都会向该参与者发送该系列中的下一个问题。这是我做过
这里有一个关于 IncludeEventHandler 的有趣问题。 我正在开发一个基于 Spring 的应用程序,该应用程序使用具有单独投资组合站点的不同供应商的速度。我让供应商通过向他们提供存储在
我真的无法理解事件和委托(delegate)的概念。我知道委托(delegate)是持有方法引用的对象,可以调用具有相同返回类型和参数的方法,但事件到底是什么? 如果我需要使用事件来制作一个简单的计算
在我正在处理的一个项目中,我有一个扩展 JFrame 的主类(名为 TrackWin)。在此框架中,我使用 JTabbedPane。 用户可以从菜单栏在 Pane 中创建新选项卡。每当发生这种情况时,
我是一名优秀的程序员,十分优秀!