我在 C++ 的学习阶段。在阅读 c++ 对象模型时,我了解了不同的对象模型。
1) 简单对象模型。
2) 表驱动对象模型。
3) c++ 对象模型。
问题:
"它的主要缺点是需要重新编译未修改的代码,这些代码利用已添加、删除或修改非静态类数据成员的类的对象。 "
我理解了上面的说法。类定义中发生的任何更改,都需要重新编译使用相同类的源代码。
这意味着,有一些为什么在不重新编译的情况下也能达到同样的效果。怎么做?如果有人提供示例代码,那就太好了。我在 Linux/Ubuntu 中使用 g++。
我在 C++ 的学习阶段。在阅读 c++ 对象模型时,我了解了不同的对象模型。
1) 简单对象模型。
2) 表驱动对象模型。
3) c++ 对象模型。
问题:
"它的主要缺点是需要重新编译未修改的代码,这些代码利用已添加、删除或修改非静态类数据成员的类的对象。 "
我理解了上面的说法。类定义中发生的任何更改,都需要重新编译使用相同类的源代码。
这意味着,有一些为什么在不重新编译的情况下也能达到同样的效果。怎么做?如果有人提供示例代码,那就太好了。我在 Linux/Ubuntu 中使用 g++。
在修改类时防止重新编译的典型习惯用法是 PImpl。
在其他语言/对象模型中可能有实现相同的方法,但在 C++ 中没有。否则,这不会是 C++ 对象模型的缺点。
然而,可以减轻后果,例如,通过 (1) 从库中仅导出接口,也就是纯抽象类,以及 (2) 从不更改已发布的接口。如果必须添加新的 API,请通过新接口将其导出(即使它引用旧的/修改的实现类)。
我不确定代码示例会有多大帮助。这不是一种编码技术。如果您知道什么是纯抽象类,那么您就大功告成了。
请注意,在标头中公开实现细节可能有好处,也有在细节更改时强制重新编译的缺点;函数可以更容易地内联,这可以提高运行时性能。您将需要决定在何时何地进行这种权衡是值得的。
通过引入额外的间接级别,可以将所有私有实现细节隐藏在源文件中。一种常见的方法是指向私有实现(或“pimpl”)的指针,例如:
// Header file
class Thing {
public:
Thing(...);
~Thing();
// Public interface
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
// Source file
struct Thing::Impl {
// private details
};
Thing(...) : impl(new Impl(...)) {}
~Thing() {}
// Implementation of public interface
另一种可能性是定义一个抽象接口,使用一个或多个工厂来创建包含实现的具体实例,例如:
// Header file
class Thing {
public:
virtual ~Thing() {}
static std::unique_ptr<Thing> make(...);
// Pure virtual public interface
};
// Source file
class ThingImpl : public Thing {
// Implementation of public interface
// Private implementation details
};
std::unique_ptr<Thing> Thing::make(...) {
return std::unique_ptr<Thing>(new ThingImpl(...));
}
这两种方法都将所有实现细节放在一个源文件中,因此当细节发生变化时,这是唯一需要重新编译的东西。但是两者都引入了额外的指针间接和/或间接函数调用,这可能会影响运行时性能。