【问题标题】:C++ / class A : public B, public C / What happens to B on ~C()?C ++ / A类:公共B,公共C /〜C()上的B会发生什么?
【发布时间】:2014-09-23 02:55:20
【问题描述】:

我想基于引用计数器为脚本引擎做某种垃圾收集:

class HeapValue
{
private:

   size_t _refCount;

public:

   HeapValue()
    : _refCount( 0 )
   { }

   virtual ~HeapValue() { }

   inline void reference() throw()
   {
      ++this->_refCount;
   }

   inline void unreference() throw()
   {
      if( 0 == --this->_refCount )
      {
         delete this;
      }
   }
};

但我的对象不仅是 HeapValues,它们也是 Scopes:

class Scope
{
protected:

   std::map< std::string, Value > _vars;

public:

   inline Value & getRef( const std::string & name ) throw()
   {
      return this->_vars[ name ];
   }

   inline Value getCpy( const std::string & name ) const
   {
      std::map< std::string, Value >::const_iterator itr = this->_vars.find( name );

      if( this->_vars.end() != itr )
      {
         return itr->second;
      }
      else
      {
         throw std::exception( "Scope::getCpy() - Accessing undeclared indentifier in readonly mode." );
      }
   }
};

class Object : public Scope, public HeapValue
{
};

假设我创建了一个对象,当 HeapValue 类删除自身时会发生什么?我假设它不会调用 Scope 析构函数,因为 Scope 不是 HeapValue ?

谢谢你:)

编辑:添加类对象定义

编辑:

我的 Value 类是一个变体:

class Value
{
private:

    union
    {
        int _i;
        double _r;
        std::string * _s; // Owned/copied
        Object * _o; // Not owned/copied
    }
    _data;

    // etc...
};

还有:

class HeapValue
{
   //...

   inline void reference() throw()
   {
      ++this->_refCount;
   }

   inline void unreference() throw()
   {
      --this->_refCount )
   }
};

Value & Value::operator = ( const Value & val )
{
    switch( this->_type )
    {
    // ...
    case E_OBJECT :
        switch( val._type )
        {
        // ...
        case E_INTEGER :
            this->_data._o->unreference();
            if( this->_data._o->getRefCount() == 0 ) delete this->_data._o; // Deletion moved here, outside of HeapValue ?
            this->_data._i = val._data.i;
            this->_type = E_INTEGER;
            break;
        // ...
        }
    }
    // ...
}

【问题讨论】:

  • 抱歉,我忘记了那段代码。
  • Scope 没有虚拟析构函数,这看起来很危险——你如何删除你的对象?
  • 我不会使用 Scope 指针删除对象。当它们的引用计数器下降到 0 时,这些对象将被删除。我也可以向 Scope 添加一个空的析构函数,但它会改变什么吗?
  • 代码不知道哪些对象在堆栈上,哪些不在。如果您调用 unreference() 并且 _refCount 为 0,它将尝试删除它。结果是未定义的(未定义的行为)。这可能会导致各种错误,通常是不可取的。
  • 是的,但我不打算在堆栈上创建它们。

标签: c++ inheritance polymorphism virtual destructor


【解决方案1】:

unreference 调用delete this 时,会进行虚方法调用(因为析构函数是虚函数)。如果对象是Object 类型,那么虚拟调用将指向Object 的析构函数,该析构函数将调用它的所有父级析构函数,包括Scope 的析构函数。

只是不要通过Scope 指针删除Object 实例,也不要在堆栈上分配HeapValue 实例或复制它们。

也就是说,我会使用 std::shared_ptr 进行引用计数。

【讨论】:

  • 好的,谢谢,我现在明白了。你认为我应该使用 Scope 作为成员变量而不是使用它作为 Object 的基类吗?
  • 嗯,可能。我没有考虑太多,但多重继承有时会变得相当棘手。
猜你喜欢
  • 1970-01-01
  • 2017-06-11
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 2010-11-27
  • 2015-06-12
相关资源
最近更新 更多