在标题中隐藏类类型 [英] Hide class type in header

查看:23
本文介绍了在标题中隐藏类类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定这是否可能,但这里是:

I'm not sure if this is even possible, but here goes:

我有一个库,它的界面充其量是复杂的.不幸的是,它不仅是一个 3rd 方库(而且太大而无法重写),我还使用了一些其他依赖于它的库.因此,该界面必须保持原样.

I have a library whose interface is, at best, complex. Unfortunately, not only is it a 3rd-party library (and far too big to rewrite), I'm using a few other libraries that are dependent on it. So that interface has to stay how it is.

为了解决这个问题,我试图从本质上包装接口并将所有依赖项的接口捆绑到更少、更具逻辑性的类中.那部分进展顺利,效果很好.大多数包装类持有一个指向原始类之一的对象的指针.像这样:

To solve that, I'm trying to essentially wrap the interface and bundle all the dependencies' interfaces into fewer, more logical classes. That part is going fine and works great. Most of the wrapper classes hold a pointer to an object of one of the original classes. Like so:

class Node
{
public:
    String GetName()
    {
        return this->llNode->getNodeName();
    }

private:
    OverlyComplicatedNodeClass * llNode; // low-level node
};

我唯一的问题是第二点.除了简化界面之外,我还想取消链接原始标题/库的要求.

My only problem is the secondary point of this. Beside simplifying the interface, I'd like to remove the requirement for linking against the original headers/libraries.

这是第一个困难.如何以不需要包含原始标题的方式包装类?包装器将构建为共享库 (dll/so),如果这样可以更简单.

That's the first difficulty. How can I wrap the classes in such a way that there's no need to include the original headers? The wrapper will be built as a shared-library (dll/so), if that makes it simpler.

原始类是指针,没有在任何导出函数中使用(尽管它们在一些构造函数中使用).

The original classes are pointers and not used in any exported functions (although they are used in a few constructors).

我玩弄了一些想法,包括预处理器的东西,例如:

I've toyed with a few ideas, including preprocessor stuff like:

#ifdef ACCESSLOWLEVEL
#    define LLPtr(n) n *
#else
#    define LLPtr(n) void *
#endif

这充其量是丑陋的.它基本上满足了我的需求,但我更喜欢那种混乱的真正解决方案.

Which is ugly, at best. It does what I need basically, but I'd rather a real solution that that kind of mess.

某种指针类型的魔法起作用了,直到我遇到了一些使用共享指针的函数(某种提供引用计数的自定义 SharedPtr<> 类),更糟糕的是,还有一些从基本的SharedPtr 类(例如NodePtr)派生的特定于类的共享指针.

Some kind of pointer-type magic works, until I ran into a few functions that use shared pointers (some kind of custom SharedPtr<> class providing reference count) and worse yet, a few class-specific shared pointers derived from the basic SharedPtr class (NodePtr, for example).

是否有可能以这样一种方式包装原始库,即只需要包含我的标头即可链接到我的动态库? 无需链接到原始库或从中调用函数,只是我的.我遇到的唯一问题是使用的类型/类.

Is it at all possible to wrap the original library in such a way as to require only my headers to be included in order to link to my dynamic library? No need to link to the original library or call functions from it, just mine. Only problem I'm running into are the types/classes that are used.

这个问题可能不是很清楚.如果有帮助,我可以尝试清理它并添加更多代码示例.我并不真正担心任何性能开销或这种方法的任何事情,只是试图让它首先起作用(过早的优化等等).

The question might not be terribly clear. I can try to clean it up and add more code samples if it helps. I'm not really worried about any performance overhead or anything of this method, just trying to make it work first (premature optimization and all that).

推荐答案

使用 Pimpl(指向实现的指针)习语.如上所述,就您的库的用户而言,OverlyComplicatedNodeClass 是一个实现细节.他们不应该知道这个类的结构,甚至它的名字.

Use the Pimpl (pointer to implementation) idiom. As described, OverlyComplicatedNodeClass is an implementation detail as far as the users of your library are concerned. They should not have to know the structure of this class, or even it's name.

当您使用 Pimpl 惯用语时,您将类中的 OverlyComplicatedNodeClass 指针替换为指向 void 的指针.只有库作者需要知道 void* 实际上是一个 OverlyComplicatedNodeClass*.所以你的类声明变成:

When you use the Pimpl idiom, you replace the OverlyComplicatedNodeClass pointer in your class with a pointer to void. Only you the library writer needs to know that the void* is actually a OverlyComplicatedNodeClass*. So your class declaration becomes:

class Node
{
public:
    String GetName();

private:
    void * impl; 
};

在您的库的实现中,使用指向执行实际工作的类的指针初始化 impl:

In your library's implementation, initialize impl with a pointer to the class that does the real work:

Node::Node()
: impl(new OverlyComplicatedNodeClass)
{
// ...
};

...并且您图书馆的用户永远不需要知道 OverlyComplicatedNodeClass 存在.

...and users of your library need never know that OverlyComplicatedNodeClass exists.

这种方法有一个潜在的缺点.所有使用 impl 类的代码都必须在您的库中实现.如果可以内联,则没有.这是否是一个缺点在很大程度上取决于您的应用程序,因此请自行判断.

There's one potential drawback to this approach. All the code which uses the impl class must be implemented in your library. None if it can be inline. Whether this is a drawback depends very much on your application, so judge for yourself.

就您的课程而言,您确实在标题中有 GetName() 的实现.必须将其移动到库中,就像所有其他使用 impl 指针的代码一样.

In the case of your class, you did have GetName()'s implementation in the header. That must be moved to the library, as with all other code that uses the impl pointer.

这篇关于在标题中隐藏类类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆