2014-12-24 4 views
0

저는 일반적으로 상호 참조를 처리하는 방법을 알고 있지만 여기서 저는 붙어 있습니다.템플릿 매개 변수를 사용할 때 교차 참조

합시다 스마트 포인터 클래스 :

template< typename T > 
SharedPointer 
{ 
    T * _ptr; 
}; 

그리고 :

class Array; 

class Value 
{ 
    SharedPointer<Array> _pa; 
}; 

그리고 : 내가 해요 SharedPointer 클래스 말에

다음
class Array 
{ 
    Value someFunc(); 
} 

난 데 경고 불완전한 유형의 객체에 대한 포인터를 삭제합니다. 이는 전방 선언으로 인한 것입니다.

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()); 
    } 
}; 
+0

'값'앞에 '배열'을 정의하십시오. 앞으로'Array'를 정의하기 전에'Value'를 선언하십시오. – juanchopanza

+0

Array에 값을 정의해야하므로 할 수 없습니다. – Virus721

+0

'Array'는'Value'의 fwd 선언만을 필요로합니다. – juanchopanza

답변

2

문제는 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 파일로 이동하십시오. 수업 외부에서 발생하는 정의에 대해서도 use the default 키워드를 사용할 수 있습니다.

+1

당신은'~ 가치'에 대해 이야기하고 있습니다. – Jarod42

+0

죄송합니다 전 예제를 단순하게 유지하기 위해 전체 코드를 게시하지 않았지만 Value에는 소멸자가 있습니다. 그러나 배열은 아닙니다. 소멸자를 Array에 추가하고 경고가 제거되었습니다. 나는 왜 그런지 이해하지 못합니다. 실제 코드를 게시합니다. – Virus721

+0

@ Virus721 코드를 살펴본 후에,'~ Value' 값을 가지고 있어도 헤더 파일에 포함되어 있기 때문에'Array'의 완전한 정의에 접근 할 수 없습니다. 단순히 헤더에 선언하고 정의를 cpp로 이동하십시오. – Pradhan