指针引用问题

3

我有一个关于指针引用的问题,或者你想怎么称呼它都可以,但首先是一些代码。首先是一个抽象的比较函数模板类:

template <class T> struct BinaryTrivalent {
    virtual BinaryTrivalent<T>* clone() const = 0;
    virtual int operator()(const T& lhs, const T& rhs) const = 0;
    int compare(const int a, const int b) const {
        if (a < b)
            return LESS_THAN;
        else if(a == b)
            return MATCH;
        return MORE_THAN;
    }
};

而它的实际使用:

struct NodePCompare : public BinaryTrivalent<Node*> {
    NodePCompare* clone() const { return new NodePCompare(*this); }
    int operator()(const Node*& lhs, const Node*& rhs) const {
        return compare(lhs, rhs);
    }
};

该模板在实际类型上运行良好,但似乎无法像我期望的那样识别运算符,并告诉我NodePCompare是抽象的。
我以前遇到过这个问题,但我放弃了尝试找出问题所在,只是用另一种类型包装了指针。
现在我可以做同样的事情,但我想了解真正的问题是什么。
我一直在阅读关于这个上下文中*&到底意味着什么的内容,除非我没有理解正确,否则这应该可以正常工作。
这个链接在理解它方面有所帮助:http://markgodwin.blogspot.co.il/2009/08/c-reference-to-pointer.html

大家有什么想法吗?


好的,NodePCompare 中的 operator() 应该是 virtual 的。 - Andy Prowl
2
它是隐式虚拟的,你可以添加 virtual 关键字只是为了自己记住它,但编译器并不需要。 - Jack
@Jack:没错,忘了这个。 - Andy Prowl
1个回答

4
你的问题是签名不匹配。 应该是这样的:
int operator()(Node* const & lhs, Node* const & rhs) const {
    return compare(lhs, rhs);
}

问题在于 const 适用的位置。你可以通过在类的私有部分中说 typedef Node * base_T_arg_t; 然后说出这句话来完成同样的事情:
int operator()(const base_T_arg_t &lhs, const base_T_arg_t &rhs) const {
    return compare(lhs, rhs);
}

基本上,* 前面的 const 并不与指针类型整体绑定,而是与类型 Node 绑定。

clone 的返回类型有两个原因是一个红鲱鱼。首先,函数签名不包括其返回类型。因此,您肯定会创建一个与原始签名匹配并因此覆盖它的 clone 定义。

但是,如果您的返回类型不匹配,则编译器通常会给出错误。除非有一个叫做 '逆变' 的原则,该原则允许在函数被覆盖时,返回类型为引用或指针的返回类型是派生类的引用或指针。

毕竟,指向派生类型的指针可以自由转换为指向基础类型的指针。在某种意义上,它们是等效的。


首先,谢谢!我想那就是它了! :) 其次:看起来你在我添加这个评论之前已经回答了它,所以再次感谢 :) - Itamar Bitton
关于“红鲱鱼”: 我是应该把它从问题中剔除掉,还是你在解释我在那里做错了什么?我的意思是,我已经提到operator()是问题所在,而不是clone() - Itamar Bitton
@itchy23:你做得很好。我只是因为另一个被删除的答案才加入了这个解释。那个人很困惑,我想以友好的方式解释为什么他们的答案是错误的。但是,他们最初给出的答案确实意味着任何其他随机的人可能会认为那也是问题所在,因此解释可能也会对他们有帮助。此外,逆变是一个很棒的概念,而且并不广为人知。所以,这也是解释它的原因。 - Omnifarious
是的,没错,我也正要评论同样的事情,但答案在我还没来得及这样做之前就消失了。再次感谢。 - Itamar Bitton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接