【问题标题】:Is this a situation where I'd want to use "using"?这是我想使用“使用”的情况吗?
【发布时间】:2011-06-23 03:55:00
【问题描述】:

我不熟悉 C++0x。大约 6 个月前我自己才开始学习 C++,不过我掌握得相当好(对于初学者来说)。

我有一个模板类:

template <typename T>
class Node
{
   ...
}

然后,我有这个:

template <typename T>
class BinaryTree
{
    protected:
       typedef Node<T>* node_t;
    ...
}

在这里,二叉树类充当“基类”,可以通过二叉树的特化来扩展。 (AVL 树、红黑等,)节点 typedef 受到保护,因为其想法是专业化将能够使用它……他们可以使用它,但它看起来很糟糕。

例如,在我的 BiTree 类(我对最通用二叉树的创意名称,基本上是 BST)中,我们有这样的:

template <typename T>
class BiTree : public BinaryTree<T>
{
   private:
      typedef typename BinaryTree<T>::node_t node_t; // Yuck
   ...
}

更糟糕的是,我是喜欢在类之外指定函数的人之一,所以当我想说 node_t 是返回类型时......好吧,看看......

template <typename T>
typename BiTree<T>::node_t
BiTree<T>::insert(BiTree<T>::node_t& node, T data)
{
   ...
}

有没有办法只使用 node_t?这就是从基类继承 typedef 的重点。这就是 C++0x 中的 using 关键字的用途吗?我将如何将其应用于这种情况?谢谢。

编辑:我想知道它是否有用的原因是因为这个问题:C++ template typedef

【问题讨论】:

  • using 不是 C++0x 中的新功能,那么您要使用什么语法?它确实被模板化的 typedef 回收了,但我不确定这是否适用于这里 [虽然我不记得它们是如何使用的,所以也许我弄错了]。
  • =( 我想知道它是否适用,因为人们在谈论模板类型定义并使用here
  • 好吧,它可以用作模板 typedef(实际上是 C++0x 中的新用途),但它与您拥有的没有任何不同。它只对你想要保留一个或多个模板参数的 typedef 有帮助,但不是全部。

标签: c++ templates inheritance c++11 typedef


【解决方案1】:

您的问题的答案是否定的,它不适用。 using 在您的意思的上下文中旨在重命名模板化类型,同时保留其模板化性质。您有一个特定的模板实例,因此不合适。

但是,您的部分担忧似乎只是函数定义中BiTree&lt;T&gt;:: 过多。对我来说似乎并没有那么糟糕。你习惯于看到这样的结构。但如果你愿意,它可以减少。

你从什么开始:

template <typename T> 
typename BiTree<T>::node_t BiTree<T>::insert(BiTree<T>::node_t& node, T data) 
{ ... } 

首先,一旦你为函数命名,你就已经在“内部”类BiTree&lt;T&gt;,所以编译器会在里面寻找你的参数类型。

template <typename T> 
typename BiTree<T>::node_t BiTree<T>::insert(node_t& node, T data) 
{ ... } 

C++0x 的另一个新特性是能够等待声明函数的结果,直到您声明其参数之后。它旨在用于结果类型取决于参数类型的情况,但出于与上述相同的原因,它在这里也很有用。编译器在分析时会考虑BiTree&lt;T&gt; 中的类型:

template<typename T>
auto BiTree<T>::insert(node_t& node, T data) -> node_t
{ ... }

几乎没有重复。从技术上讲,您可以更进一步:

template<typename T>
auto BiTree<T>::insert(node_t& node, T data) 
     -> std::remove_reference<decltype(node)>::type
{ ... }

现在,您甚至不需要重复参数类型,但要使返回类型正确显然更加困难 [正如我最初弄错的事实所证明的那样 ;-)]。

【讨论】:

  • 我只是想在你的答案弹出时编辑我的答案中的尾随返回版本。 +1:P
  • 正要准确地发布这个:)
  • 正是我想要的!非常感谢你。我不介意打字,但我觉得我的东西有点太多了。
  • "从技术上讲,您可以更进一步",不,那是不同的 :) 由于 node 被声明为 node_t&amp;,您将返回对 node_t 的引用。在这里使用尾随返回类型的好主意。
【解决方案2】:

Ehm...基类类型定义在派生类中可用,没有任何恶作剧,只需使用node_t(尽管_t is a bad suffix,因为所有以它结尾的名称都是POSIX标准保留的)。但是我想知道,如果您想从 insert 返回这样的节点,为什么要使用 protected / private ?应该如何使用它,因为类层次结构之外的任何人都不能使用node_t

【讨论】:

  • 节点类中的所有内容都是公共的,只有 typedef 是受保护的/私有的。人们可以访问被退回的东西。可以查看完整代码here
  • 我不记得 _t 是标准保留的任何内容 - 实际上 wchar_t 是根据人们使用的预标准 typedef 最常见的名称命名的。不过我可能是错的!
  • @Simon:我知道它是由标准保留的,但不完全是由哪个标准保留的。稍作搜索,我找到了我在其中编辑的链接 - 它是 POSIX。
猜你喜欢
  • 2015-07-14
  • 1970-01-01
  • 2011-06-27
  • 2011-01-17
  • 2012-03-28
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多