【发布时间】:2017-08-02 01:00:03
【问题描述】:
已编辑较短的问题: 当使用指向抽象类的指针时,如何调用它所指向的对象的实际类型的方法?
我有一个带有公共的抽象 BaseTree 类
virtual BaseTree const& operator[](NodeIndex const& poss) const = 0;
NodeIndex 在实践中是std::vector<unsigned int>。我还有一个TreeBasicIterator 课程,其中包括
public:
/// Access the tree to which m_tree points
BaseTree& operator*() const
{
//checking...
return (*m_tree)[*this];
}
private:
/// the tree the current iterator refers to
BaseTree* m_tree=nullptr;
问题(我认为这是我下面最初问题的症结所在):
如何使用与*m_tree的实际类型对应的类的方法?目前,在取消引用我的迭代器时,我只能使用抽象类 BaseTree 的方法。
我想避免将TreeBasicIterator 设为模板(请参阅下面的初始问题)。
初始问题
C++ 的许多(相对较新?)用户,我想写
virtual typedef something my_virtual_type;
在类定义中。不幸的是,这是不可能的......
最流行的替代方案似乎是模板,例如在alternative to virtual typedef 中提供了一个很好的总结。
但是我不确定它是否涵盖了虚拟类型定义的所有内容。我在下面提出一个问题,我希望有虚拟类型定义。我有一个(临时?)使用重载而不是模板的工作解决方案。
我想创建一个花哨的树结构,包括迭代器。
1) 我定义了一个 NodeIndex 类型,它是我未来迭代器的祖先。 (NodeIndex 在我的情况下是 std::vector<unsigned int>,但没关系。)
2) 我定义了一个抽象的BaseTree 类,在下面的迭代器中使用。该类特别包括返回NodeIndex索引以在树中移动的虚拟方法(例如NodeIndex begin())和operator[](NodeIndex const&)。
3) 我定义了一个TreeBasicIterator 类,继承自NodeIndex,出于连贯性目的,该类包括对BaseTree 的常量引用,并实现了各种迭代器方法(利用BaseTree 提供的虚方法)。
(我实际上有两个类:TreeBasicIterator 和 Const_TreeBasicIterator,带有对 const BaseTree 的 const 引用;我使用预处理器宏来模拟基于 const 的模板,但这是另一个问题。)
4)我定义了一个TreeNode<T>模板类(T是节点内容),继承自BaseTree。现在它的begin() 方法返回一个NodeIndex,它的operator[] 接受一个NodeIndex 作为参数,一切正常。
5) 但是我想将我的TreeBasicIterator 包含在我的TreeNode 类中。我想包括一个
virtual typedef NodeIndex Iterator;
在我的BaseTree 类中,将虚拟begin() 方法签名修改为Iterator begin()。
然后TreeNode 将包含一个
virtual typedef TreeBasicIterator Iterator;
它的begin() 方法签名将是Iterator begin(),
希望一切都会好起来的:)
6) 我不想在TreeBasicIterator 上使用模板:它现在只编译一次。
将BaseTree 设为模板将使TreeBasicIterator 成为模板,因此会失去BaseTree 中抽象的部分好处。
将BaseTree 与NodeIndex 实例化为Iterator 类型将是多余的:实际上没有人会从该特定实例继承。
7) 预期:
我将使用具有固定或很少修改结构的树,但更频繁地修改节点内容,甚至更频繁地读取访问。为了优化访问,我打算进一步从TreeNode 派生一个TreeVector 类,其中将包含NodeIndex(或BasicTreeIterator?)索引的排序详尽的std::vector。 TreeVector 中的 Iterator 虚拟类型将是 std::iterator。
8) 当前(临时?)部分可行的解决方案:
TreeNode 定义(通过通常的typedef)一个Iterator 类型(我的TreeBasicIterator 类)。它不会覆盖 BaseTree 中的 Iterator 类型,但可以。
BaseTree 有一个NodeIndex begin() const 方法,该方法既不隐藏,又在TreeNode 中通过Iterator begin() const 方法重载。它没有被覆盖。
同样,我在BaseTree 中有一个NodeIndex next_index(NodeIndex) const,它既未隐藏,又通过Iterator next_index(Iterator) const 方法在TreeNode 中重载。
【问题讨论】:
-
C++ 不能以这种方式工作。故事结束。
-
@Sam:我知道。我正在寻找一种可能比我在第 8 点中的解决方案更有效的替代方案)
-
由于我是新人,也许 cmets 解释反对票会对我有所帮助
标签: c++ templates inheritance iterator