【问题标题】:c++ template Incomplete type using pointer of class inside templatec ++模板不完整类型使用模板内的类指针
【发布时间】:2019-06-21 10:31:54
【问题描述】:

我正在尝试创建一个网格,据我了解,问题来自在其自身内部使用模板类的指针,这是合法的,直到我尝试用它做事时编译器抱怨。我正在寻找一种在其自身内部使用指向模板类的指针的方法,以用于使用指针并执行我稍后将要做的事情。我用 g++ 版本 5 编译我使用的编译命令是 g++ *.cpp -o main -std=c++11 我得到的错误将遵循代码的 sn-p。

struct Vector2D 
{
    Vector2D(  ) {  }
    Vector2D( int x , int y ): x( x ) , y( y ) {  } ;

    int x , y ; 

} ;

template <typename A>
class GridNode2D ; 

template <typename T>
class GridNode2D
{
public: 
    GridNode2D(  ) {  } ;
    T data ; 
    Vector2D coOrdinate ; 

    GridNode2D<T>* left, right, up, down ; 

} ;

template <typename T>
class Grid2D
{
public:
    Grid2D(  ) ;

    GridNode2D<T>* head ; 

} ;

template <typename T>
Grid2D<T>::Grid2D(  )
{
    this->head = new GridNode2D<T> ; 
    this->head->right = new GridNode2D<T> ; 

} ;

错误:

main.cpp: In instantiation of ‘class GridNode2D<bool>’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',39)">main.cpp:39:16</span>:   required from ‘Grid2D<T>::Grid2D() [with T = bool]’
<span class="error_line" onclick="ide.gotoLine('main.cpp',47)">main.cpp:47:18</span>:   required from here
main.cpp:22:26: error: ‘GridNode2D::right’ has incomplete type
     GridNode2D<T>* left, right, up, down ; 
                          ^
main.cpp:15:7: note: definition of ‘class GridNode2D’ is not complete until the closing brace
 class GridNode2D
       ^
main.cpp:22:33: error: ‘GridNode2D::up’ has incomplete type
     GridNode2D<T>* left, right, up, down ; 
                                 ^
main.cpp:15:7: note: definition of ‘class GridNode2D’ is not complete until the closing brace
 class GridNode2D
       ^
main.cpp:22:37: error: ‘GridNode2D::down’ has incomplete type
     GridNode2D<T>* left, right, up, down ; 
                                     ^
main.cpp:15:7: note: definition of ‘class GridNode2D’ is not complete until the closing brace
 class GridNode2D

【问题讨论】:

    标签: c++ c++11 templates pointers compilation


    【解决方案1】:

    星号*在声明中的位置

    GridNode2D<T>* left, right, up, down ;
    

    具有误导性。 “标准”的 C 声明方式会更清楚:

    GridNode2D<T> *left, right, up, down ;
    

    在上面更清楚的是,星号属于left 的声明,这就是您遇到的问题:您只将left 声明为指针,而不是其他变量。

    由于其他变量不是指针,您需要GridNode2D&lt;T&gt; 的完整定义才能定义该类的实例,但这是不可能的,因为对象是GridNode2D&lt;T&gt; 本身的一部分。这会导致您遇到错误。

    要么在声明中的所有变量上使用星号,要么为了更好的可读性将声明分成多行:

    GridNode2D<T>* left;
    GridNode2D<T>* right;
    GridNode2D<T>* up;
    GridNode2D<T>* down;
    

    【讨论】:

      【解决方案2】:

      声明

      GridNode2D<T>* left, right, up, down ;
      

      创建 1 个指针和 3 个实例。 改成

      GridNode2D<T>* left, *right, *up, *down;
      

      甚至

      GridNode2D<T>* left = nullptr;
      GridNode2D<T>* right = nullptr;
      GridNode2D<T>* up = nullptr;
      GridNode2D<T>* down = nullptr;
      

      【讨论】:

      • 人们需要停止教学才能把星号放在左边。这正是它属于右边的原因。
      • @DanBechard:这是值得商榷的(我通常会说指针属于类型(你可能会 typedef 它们)),它通常只是文体问题。问题主要是一个衬里多重声明(允许一些混合)。
      • 属于名称,不属于类型。即使在 typedef 的情况下,它也是 typedef 名称的一部分。这就是自 C decls 以来它的工作方式。这不是风格……这是类型声明解析器的工作方式。虽然它很愚蠢..这就是为什么许多现代语言都改变了它(例如 Golang)。如果您对更复杂的情况感到好奇,这可以很好地涵盖它(对于 C,即使它支持 Golang):blog.golang.org/declaration-syntax
      • 简短的解释是 int *x; 被解析器读取为“取消引用名称 x 给我一个 int 类型的结果”,not “x 的类型是一个指向 int 的指针”,尽管大多数人在说话时都是这样描述它的。当你有更复杂的类型声明时,这很重要,但对于一个简单的指针,很难说服人们正确的星号在技术上更正确。
      • 解析器和含义可能与 IMO 不匹配(您可能有正确的加法递归规则,而它是左关联的;令牌 &gt;&gt; 现在在模板声明中的解释不同)。很难说指针属于using intptr = int*; 中的intptr。同样,我发现很难将* 与未命名的参数关联为void f(int *)。解析确实解释了正确的逻辑。格式化程序允许使用这两种样式。我主要将其视为const 的位置(我也更喜欢“错误”订单const int*)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2021-12-11
      相关资源
      最近更新 更多