我在一个库中有多个类,这些类具有我希望对客户端代码隐藏的内部结构。从客户端的角度来看,每个类都是从一个库类中查询出来的,并且只用作一个不透明的指针。一个例子如下:
struct SomeSystem;
void doSomethingToSomeSystem(SomeSystem* system, Parameters params);
void doSomethingElseToSomeSystem(SomeSystem* system, Parameters params);
在实现方面, SomeSystem 有多个调用者不可见的成员。这一切都很好,但我不太喜欢笨拙的用法语法:
SomeSystem* system = lib->getSomeSystem();
doSomethingToSomeSystem(system, params);
doSomethingElseToSomeSystem(system, params);
另一种方法是:
struct SomeSystem;
namespace somesystem {
void doSomething(SomeSystem* system, Parameters params);
void doSomethingElse(SomeSystem* system, Parameters params);
}
使用代码:
SomeSystem* system = lib->getSomeSystem();
somesystem::doSomething(system, params);
somesystem::doSomethingElse(system, params);
如果另一种类型也doSomething
定义了. 但是,在这种情况下,很难在 IDE 中找到 SomeSystem 的所有“成员”。doSomethingElse
doSomething
我很想实际使用成员函数:
struct SomeSystem {
void doSomething(Parameters params);
void doSomethingElse(Parameters params);
};
使用代码:
SomeSystem* system = lib->getSomeSystem();
system->doSomething(params);
system->doSomethingElse(params);
最后一个片段对我来说看起来不错,但 SomeSystem 不再是一个不透明的指针——它实际上定义了成员。我对此有点警惕。一个潜在的问题是单一定义规则。但是,类的“公共”定义和“私有”定义将只对不同的翻译单元可见。这里是否还隐藏着其他不好的东西?如果客户端代码尝试在堆栈上实例化 SomeSystem 或使用 new 它显然会使程序崩溃。但我愿意接受。也许我可以通过在公共接口中提供一个私有构造函数来解决这个问题。
另一种方法当然是用纯虚方法定义一个抽象类。但是,如果不是绝对必要,我想避免这种开销。
编辑:
为了清楚起见,我想知道客户端包含的公共标头包含与实现使用的类的不同定义(缺少一些成员)是否合法,因为客户端从不实例化该类。
公共标头:
struct SomeSystem {
void doSomething(Parameters params);
void doSomethingElse(Parameters params);
};
私人标头:
struct SomeSystem {
Member member;
void doSomething(Parameters params);
void doSomethingElse(Parameters params);
};
私有源(包括私有标头):
void SomeSystem::doSomething(Parameters params) {
...
}
void SomeSystem::doSomethingElse(Parameters params) {
...
}
这在我测试时有效,但我不确定它是否以某种方式违反标准。这两个标题永远不会包含在同一个翻译单元中。