继承 - 初始化问题

时间:2010-04-17 20:25:42

标签: c++

我有一个从框架中的基类派生的c ++类。

派生类没有任何数据成员,因为我需要它可以自由转换为基类并返回 - 框架负责加载和保存对象,我无法更改它。我的派生类只具有访问数据的功能。

但是有几个地方我需要存储一些临时的局部变量来加速对基类中数据的访问。

mydata* MyClass::getData() {
   if ( !m_mydata ) { // set to NULL in the constructor
      m_mydata = some_long_and complex_operation_to_get_the_data_in_the_base()
   }  
   return m_mydata;
}

问题是如果我只是通过将从框架返回的基类指针转换为MyClass *来访问该对象,则永远不会调用MyClass的ctor并且m_mydata是垃圾。
有没有办法只初始化m_mydata指针一次?

3 个答案:

答案 0 :(得分:1)

您可以在单独的初始化成员函数中初始化您的私有变量,如下所示:

class MyClass {
  public:
    init() {
      if (!m_mydata) {
        m_mydata = f();
      }
    }
};

framework_class_t *fclass = framework.classfactory.makeclass();
MyClass *myclass = (MyClass*)fclass;
myclass->init();
char *mydata = myclass->getData();

如果不了解您正在使用的框架或查看代码,很难说这是不是一个好主意。这是阅读完描述后首先想到的内容。

答案 1 :(得分:1)

您可以为框架的工厂创建一个包装器。包装器将具有相同的接口,委托对框架的调用,但它可以在返回之前初始化创建的基类实例。当然,这需要您更改代码以在任何地方使用包装器,但如果可能,那么您可以确保初始化正确发生。

对此的变体:通过将基类实例包装到自定义autopointer中来使用RAiI,该自定义可以在其构造函数中进行初始化。同样,如果您设法在任何地方更改代码以直接使用新的包装类型而不是派生类,那么您就是安全的。

答案 2 :(得分:1)

它没有成员,你必须保持逐位的内存布局兼容性...除了它,C ++没有可自由转换的概念。

如果现有框架分配基础对象,则实际上无法从中派生。在这种情况下,我可以考虑两个选项:

  • 定义您自己的班级Cached,该班级通过引用链接到Base。将引用设为公共和/或重复Base的接口而不继承。
  • 使用哈希表unordered_map< Base *, mydata > mydata_cache;。这似乎对我来说最合适。在委派给Base *
  • 之前,使用自由函数查找缓存数据