Я обычно знаю, как бороться с перекрестными ссылками, но здесь я застрял.
Пусть умный указатель класса:
template< typename T >
SharedPointer
{
T * _ptr;
};
А также :
class Array;
class Value
{
SharedPointer< Array > _pa;
};
А также :
class Array
{
Value someFunc();
}
Здесь у меня есть предупреждения в классе SharedPointer о том, что я удаляю указатели на объекты неполного типа, что, я думаю, связано с предварительным объявлением.
Warning 2 warning C4150: deletion of pointer to incomplete type 'script::Array'; no destructor called c:\XXXXX\SharedPointer.h 77
Что я мог сделать, чтобы решить это? Единственное решение, которое я вижу, это переписать весь класс SharedPointer в нечто вроде:
template< typename pT >
SharedPointer
{
pT _ptr;
};
И используйте это так вместо этого:
SharedPointer< Array * >
Я хотел бы избежать переписывания этого класса, если это возможно. Есть ли другое решение?
Спасибо 🙂
РЕДАКТИРОВАТЬ: Вот реальный исходный код:
class Value
{
PUBLIC enum type_e
{
E_NULL,
E_INT,
E_FLOAT,
E_STRING,
E_ARRAY,
E_MAP,
E_FUNCTION,
E_REFERENCE // TODO For functions like fn( scalar & val )
};
PRIVATE union
{
int _i;
float _f;
std::string * _ps;
IFunction * _pf;
};
PRIVATE SharedPointer< Array > _pa;
PRIVATE SharedPointer< Map > _pm;
PRIVATE SharedPointer< Value > _ref;
PRIVATE type_e _type;
PUBLIC Value();
PUBLIC Value( bool b );
PUBLIC Value( int i );
PUBLIC Value( float f );
PUBLIC Value( const std::string & s );
PUBLIC Value( SharedPointer< Array > pa );
PUBLIC Value( SharedPointer< Map > pm );
PUBLIC Value( IFunction * pf );
PUBLIC Value( SharedPointer< Value > ref );
PUBLIC Value( const Value & v );
PUBLIC ~Value() { }
PUBLIC Value operator + ( const Value & v ) const;
PUBLIC Value operator - ( const Value & v ) const;
PUBLIC Value operator * ( const Value & v ) const;
PUBLIC Value operator / ( const Value & v ) const;
PUBLIC Value operator % ( const Value & v ) const;
PUBLIC Value operator ^ ( const Value & v ) const;
PUBLIC Value operator << ( const Value & v ) const;
PUBLIC Value operator - () const;
PUBLIC Value operator && ( const Value & v ) const;
PUBLIC Value operator || ( const Value & v ) const;
PUBLIC Value xor( const Value & v ) const;
PUBLIC Value operator ! () const;
PUBLIC Value & operator = ( const Value & v );
PUBLIC Value operator () ( Scope & scope, const std::vector< Value > & args ) const;
PUBLIC Value & getRef( const Value & v ) const;
PUBLIC Value getCpy( const Value & v ) const;
PUBLIC inline type_e getType() const throw() { return _type; }
PUBLIC inline bool isNull() const throw() { return E_NULL == _type; }
PUBLIC inline bool isInt() const throw() { return E_INT == _type; }
PUBLIC inline bool isFloat() const throw() { return E_FLOAT == _type; }
PUBLIC inline bool isString() const throw() { return E_STRING == _type; }
PUBLIC inline bool isArray() const throw() { return E_ARRAY == _type; }
PUBLIC inline bool isMap() const throw() { return E_MAP == _type; }
PUBLIC inline bool isFunction() const throw() { return E_FUNCTION == _type; }
PUBLIC inline bool isReference() const throw() { return E_REFERENCE == _type; }
PUBLIC inline bool isNumeric() const throw() { return E_INT == _type || E_FLOAT == _type; }
PUBLIC type_e toNumeric( int & asInt, float & asFloat ) const;
PUBLIC std::string toString() const;
PUBLIC operator bool () const throw();
};
class Array
{
PRIVATE std::vector< Value > _items;
PUBLIC Array( const std::vector< Value > & items );
PUBLIC ~Array();
PUBLIC Value & getRef( int index );
PUBLIC Value getCpy( int index ) const;
PUBLIC int getSize() const;
};template< typename T >
class SharedPointer
{
template< typename U >
friend class SharedPointer;
PRIVATE T * p;
PRIVATE size_t * c;
PUBLIC SharedPointer()
: p()
, c() { }
PUBLIC explicit SharedPointer( T * s )
: p( s )
, c( new size_t( 1 ) ) { }
PUBLIC SharedPointer( const SharedPointer & s )
: p( s.p )
, c( s.c )
{
if( this->c )
{
++*(this->c);
}
}
PUBLIC SharedPointer & operator = ( const SharedPointer & s )
{
if( this != & s )
{
this->clear();
this->p = s.p;
this->c = s.c;
if( this->c )
{
++*(this->c);
}
}
return *this;
}
PUBLIC template< typename U >
SharedPointer( const SharedPointer< U > & s )
: p( s.p )
, c( s.c )
{
if( c )
{
++*(this->c);
}
}
PUBLIC ~SharedPointer()
{
this->clear();
}
PUBLIC void clear()
{
if( this->c )
{
if( *(this->c) == 1 )
{
delete this->p;
}
if( ! --*(this->c) )
{
delete this->c;
}
}
this->c = NULL;
this->p = NULL;
}
PUBLIC T * get() const
{
return this->c ? this->p : NULL;
}
PUBLIC T * operator -> () const
{
return this->get();
}
PUBLIC T & operator * () const
{
return *(this->get());
}
};
Проблема в том, что с Value
не имеет деструктора, деструктор по умолчанию создан для вас. Поскольку он в конечном итоге определяется как встроенный, в определении класса вы в конечном итоге удаляете неполный тип. Другими словами, это как если бы вы написали это в своем заголовочном файле:
class Value
{
SharedPointer< Array > _pa;
~Value() { //This will end up calling the destructor for `_pa`. To do that, if needs `Array` to be a completely defined type. }
};
Сделайте деструктор явным и переместите его в файл cpp. Обратите внимание, что вы можете использовать default
ключевое слово для определений, встречающихся и вне класса.