引用超类

时间:2014-03-04 12:07:29

标签: c++

我想将访问者模式与智能指针结合使用,但似乎编译器无法检测子类并匹配相应的函数。

我写了一个显示问题的SSCE:

test.hpp:

class Visitor;
class Area {
public:
    virtual void visit(const Visitor& visitor) = 0;
};

class Area1 : public Area {
public:
    virtual void visit(const Visitor& visitor);
};

class Area2 : public Area {
public:
    virtual void visit(const Visitor& visitor);
};

class Visitor {
public:
  virtual void visit(const Area1 &area) const = 0;
  virtual void visit(const Area2 &area) const = 0;
};

TEST.CPP:

#include "test.hpp"

void Area1::visit(const Visitor& visitor) {
    visitor.visit(*this);
}

void Area2::visit(const Visitor& visitor) {
    visitor.visit(*this);
}

的main.cpp

#include <iostream>
#include "boost/shared_ptr.hpp"
#include "test.hpp"

class FooVisitor : public Visitor {
    virtual void visit(const Area1 &area) const {
        std::cout <<"visit area1" <<std::endl;
    };
    virtual void visit(const Area2 &area) const {
        std::cout <<"visit area2" <<std::endl;
    }
};

int main(int argc, char** argv) {
    boost::shared_ptr<Area> p(new Area2);
    FooVisitor visitor;
    visitor.visit(*p);
    return 0;
}

visitor.visit(* p)行会出现此错误:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:17:21: error: no matching function for call to ‘FooVisitor::visit(Area&)’
main.cpp:17:21: note: candidates are:
main.cpp:6:18: note: virtual void FooVisitor::visit(const Area1&) const
main.cpp:6:18: note:   no known conversion for argument 1 from ‘Area’ to ‘const Area1&’
main.cpp:9:18: note: virtual void FooVisitor::visit(const Area2&) const
main.cpp:9:18: note:   no known conversion for argument 1 from ‘Area’ to ‘const Area2&’

如何帮助编译器实现访问(const Area2&amp;)而不需要尝试使用dynamic_cast到每个子类型?

2 个答案:

答案 0 :(得分:7)

这不起作用,因为*p的类型确实是Area&(基于指针的类型)。但是,你错了。要正确应用访问者模式,您应该调用visit()中定义的Area,以获得正确的调度:

int main(int argc, char** argv) {
    boost::shared_ptr<Area> p(new Area2);
    FooVisitor visitor;
    p->visit(visitor);
    return 0;
}

首先是Area::visit()功能的目的。

答案 1 :(得分:0)

您的访客类有两种访问(...)方法:

虚空访问(const Area1&amp; area) 无效访问(const Area2&amp; area)

因此,要从访问者对象显式调用visit方法,您需要将引用/指针传递给Area1对象或Area2对象。 由于您传递了Area对象,因此您需要执行dynamic_cast才能生效。

但您之前的答案总结了代码中的实际问题 - &gt; 你使用它错了。你的代码应该做类似的事情

Area *p = new Area2();
FooVisitor v;
p->visit(v);

这样就可以利用代码中的多态性。