2012-10-22 71 views
0

我有以下代码:C++:不完全类型

template<class T> 
class RandomTreeNode { 

public: 
    typedef typename RandomTreeFunction<T>::function_ptr function_ptr; 
    RandomTreeNode(): left(NULL), right(NULL), threshold(0.0), is_a_leaf(false), data(NULL), function(0){ 
    } 
    void set_function(function_ptr function){this->function = function;} 
    function_ptr get_function(){ return this->function;} 

    void set_threshold(double threshold){this->threshold = threshold;} 
    double get_threshold(){return threshold;} 

    void create_left_child(){this->left = RandomTreeNode<T>();} 
    //returning references so that they can be altered in a recursive tree build algo without excessive copying 
    RandomTreeNode<T>& get_left_child(){return left;} 

    void create_right_child(){this->right = RandomTreeNode<T>();} 
    RandomTreeNode<T>& get_right_child(){return this->right;} 

    bool is_leaf(){return this->is_a_leaf;} 
    void mark_as_leaf(){this->is_a_leaf = true;} 

    const std::vector<T> get_data(){ 
     return data; 
    } 
    void set_data(std::vector<T>& data){ 
     this->data = data; 
    } 

private: 
    RandomTreeNode<T> left; 
    RandomTreeNode<T> right; 
    double threshold; 
    function_ptr function; 
    std::vector<T> data; 
    bool is_a_leaf; 

}; 

当我编译,我得到以下error: 'RandomTreeNode<T>::left' has incomplete type。任何想法为什么?

回答

3

因为它是您当前定义的类型。一个类型具有相同类型的成员是没有意义的(对于初学者来说,它将具有无限大小)。我想你想要的是指针RandomTreeNode<T>的,而不是直接的实例。

+0

啊,好吧,这是有道理的。由于 – Aly

+2

@Aly而不是将其更改为'RandomTreeNode *左;'请改为'的std ::的unique_ptr >离开;' – Praetorian

+0

会怎么create_left_child码的样子,因为ATM我已经离开= RandomTreeNode ( );但这是因为我正在一个临时变量 – Aly

-1

尝试前向声明。在全球范围内的程序开始处写下此内容。

template<class T> 
class RandomTreeNode ; 

它给你错误,因为你声明你要声明的类型的变量。

+0

不傻,你需要的是一个编译器,它允许以无限的大小声明类。一旦你有了,你就全都定了。 – Praetorian

+0

好的,我很抱歉的错误 – Sasha

1

你不能在这个类中声明一个类的实例。

在这里,您声明RandomTreeNode<T> left;RandomTreeNode<T> right;您的RandomTreeNode的声明中。因此该类型的声明不完整。

您应该使用指向RandomTreeNode<T>的指针来避免此错误。这是正确编译

0

代码(http://codepad.org/ltpxM60i)

下面代码现在正确编译

**template<class T> 
class RandomTreeFunction{ 
     class function_ptr{ 
     }; 
};** 
template<class T> 
class RandomTreeNode { 

public: 
    typedef typename RandomTreeFunction<T>::function_ptr function_ptr; 
    RandomTreeNode(): left(NULL), right(NULL), threshold(0.0), is_a_leaf(false), data(NULL), function(0){ 
    } 
    void set_function(function_ptr function){this->function = function;} 
    function_ptr get_function(){ return this->function;} 

    void set_threshold(double threshold){this->threshold = threshold;} 
    double get_threshold(){return threshold;} 

    void create_left_child(){this->left = RandomTreeNode<T>();} 
    //returning references so that they can be altered in a recursive tree build algo without excessive copying 
    RandomTreeNode<T>& get_left_child(){return left;} 

    void create_right_child(){this->right = RandomTreeNode<T>();} 
    RandomTreeNode<T>& get_right_child(){return this->right;} 

    bool is_leaf(){return this->is_a_leaf;} 
    void mark_as_leaf(){this->is_a_leaf = true;} 

    const std::vector<T> get_data(){ 
     return data; 
    } 
    void set_data(std::vector<T>& data){ 
     this->data = data; 
    } 

private: 
    RandomTreeNode<T> left; 
    RandomTreeNode<T> right; 
    double threshold; 
    function_ptr function; 
    std::vector<T> data; 
    bool is_a_leaf; 

}; 
int main(){ 
return 0; 
} 

,我认为是没有定义function_ptr

typedef typename RandomTreeFunction<T>::**function_ptr** function_ptr; 

对于typename以下是适用于此处的规则(参考: - http://pages.cs.wisc.edu/~driscoll/typename.html

规则

typename is prohibited in each of the following scenarios: 
     Outside of a template definition. (Be aware: an explicit template specialization (more commonly called a total specialization, to contrast with partial specializations) is not itself a template, because there are no missing template parameters! Thus typename is always prohibited in a total specialization.) 
     Before an unqualified type, like int or my_thingy_t. 
     When naming a base class. For example, template <class C> class my_class : C::some_base_type { ... }; may not have a typename before C::some_base_type. 
     In a constructor initialization list. 
    typename is mandatory before a qualified, dependent name which refers to a type (unless that name is naming a base class, or in an initialization list). 
    typename is optional in other scenarios. (In other words, it is optional before a qualified but non-dependent name used within a template, except again when naming a base class or in an initialization list.) 

所以,你可能要为function_ptr定义类型。