C ++继承 - 将指向此类的指针作为参数

时间:2017-03-13 16:51:26

标签: c++ oop inheritance

假设我有一个对象Node,它有一个函数addPath(),期望另一个Node作为参数。

virtual void Node::addPath(Node * otherNode)
{
     // does something with otherNode
}

现在,我说我来自Node。让我们调用此DerivedNode,它有一个新函数foo()。我想覆盖addPath方法。我也知道当我拨打DerivedNode::addPath时,参数将始终是另一个DerivedNode。这意味着我希望能够在foo()方法中调用addPath()

int DerivedNode::foo(); 

void DerivedNode::addPath(Node * otherNode)
{
     int x = foo();   // no problem
     int y = otherNode->foo()   // BAD! otherNode is typed as Node, not DerivedNode
}

我无法致电otherNode->foo()。我该怎么办?

显然我知道我可以投,但这似乎是一个笨重的新手解决方案。我们有更优雅的东西吗?我觉得这应该是一个相当常见的用例。

4 个答案:

答案 0 :(得分:1)

除非你在基类中设置类似的内容,否则你必须进行强制转换。但是所有派生类都需要实现它,取决于你的程序。

virtual int foo() = 0;

答案 1 :(得分:0)

您不能调用'foo'方法,因为它不是基本节点的成员。实际上,您可以进行转换,但要确保节点参数的类型确实是DerivedNode,否则您将获得异常。 是的,您可以从addPath方法调用x = foo()方法,因为您正在从DerivedNode类进行调用。

或者您可以将foo()定义为基类中的虚方法。要么使它抽象,但在这种情况下,您将无法创建Node实例,或者您可以提供默认/空实现。

答案 2 :(得分:0)

假设您的Node类是2种节点的抽象类:

  • 你将拥有执行某些功能的叶子节点
  • 你将拥有复合节点,它将存储其他节点

在这种情况下,出现了两个问题:

  1. 为什么基类具有'addNode'方法?叶子节点对它没有任何用处......
  2. foo()做什么?也许在基类中添加'addNode',然后将'foo()'变成模板方法将是一个很好的方法。
  3. 一旦你回答了这些问题,你就可以更清楚地了解这些方法所承担的责任 - 而这反过来会给你一个提示 (在哪个班级中)给它们。

答案 3 :(得分:-1)

如果只有一个派生类需要foo()操作,那么你应该使用动态强制转换(或重新考虑你的设计)。

如果" foo" operation是一个适用于多个派生类的操作,那么你应该在你的基类(Node)中添加一个虚方法foo()。

  • 如果(几乎)每个派生类都需要某种类型的foo操作,那么使foo()方法成为抽象(纯粹的。)

  • 如果许多派生类不需要foo()操作,那么将其作为" no-operation"在基类中,所以不需要foo()的派生类可以简单地忽略该问题。

以下代码使用此技术。

class Node
{
    virtual void Node::addPath(Node * otherNode)
    {
         // does something with otherNode
    }
    virtual void foo()
    {
        // nothing to do in the base class
    }
};

class DerivedNode : public Node
{
    void DerivedNode::addPath(Node * otherNode)
    {
        int x = foo();   // no problem
        int y = otherNode->foo(); // Now this works.
    }
    void foo()
    {
        // this is the DervivedNode-specific foo!
        Node::foo(); // just in case the base class has an opinion
        do my foo-ish stuff here;
    }
};