模板派生 class 中的错误 "Pure virtual function called"
Error "Pure virtual function called" in template derived class
我需要做一个通用的 Robot
,它将在通用的 Surface
上找到路径。
所以这是我的 Surface
界面:
template <typename P>
class Surface {
public:
virtual int distance(const P& from, const P& to) const = 0;
virtual bool check(const vector<P>& path, const P& from, const P& to) const = 0;
virtual vector<P> lookAround(const P& at) const = 0;
};
这里我创建一个简单的PlanarSurface
:
class PlanarSurface : public Surface<pair<int, int>> {
public:
using point_type = pair<int, int>;
int distance(const point_type& from, const point_type& to) const override {
return to.first - from.first + to.second - from.second;
}
bool check(const vector<point_type>& path,
const point_type& from,
const point_type& to) const override {
return true; // there would be the check
}
vector<point_type> lookAround(const point_type& at) const override {
vector<point_type> result;
//...
return result;
}
};
现在我创建一个抽象 class Robot
这样每个 user-implemented 机器人都会扩展它:
template <typename P>
class Robot {
public:
Robot(const Surface<P>& s): surface(s) {}
vector<P> findPath(const P& from, const P& to) {
auto path = searchPath(from, to);
if (surface.check(path, from, to)) {
return path;
}
throw runtime_error("path not found or incorrect");
}
private:
virtual vector<P> searchPath(const P& from, const P& to) = 0;
protected:
const Surface<P>& surface;
};
searchPath
私有方法将负责自定义搜索算法,定义在 Robot
的 children 中。
假设我有一个:
template <typename P>
class MyRobot: public Robot<P> {
public:
MyRobot(Surface<P> m): Robot<P>(m) {}
private:
vector<P> searchPath(const P& from, const P& to) override {
vector<P> result;
// ...
// use one of surface's virtual methods
auto dist = this->surface.distance(from, to); // Pure virtual function called!
cout << dist << endl;
// ...
return result;
}
};
最后是 main
函数:
int main(const int argc, const char **argv) {
PlanarSurface plane;
MyRobot<pair<int, int>> robot(plane);
robot.findPath({1,2}, {3,4});
return 0;
}
所以问题是,由于对 surface
的引用存储在基 Robot
class 中,我们无法用 Surface
的某些派生来指定它的类型 class。所以引用的类型只能是Surface<P, M>
.
我们需要在 Robot
的每个 child 的搜索算法中使用 surface
的 distance
和 lookAround
方法。但在 Surface<P, M>
它们是纯虚拟的。而且只能在children of Surface<P, M>
.
中实现
请帮帮我!也许我错过了一些明显的东西..
错误在这里:
MyRobot(Surface<P> m) : Robot<P>(m) {}
^^^^^^^^^^^^ value
改为接受引用
MyRobot(Surface<P>& m) : Robot<P>(m) {}
有趣的是,MSVC 和 gcc 都根据
诊断这个问题
invalid abstract parameter
虽然 clang 甚至没有对此发出警告(在撰写本文时 post - 4.0)
我需要做一个通用的 Robot
,它将在通用的 Surface
上找到路径。
所以这是我的 Surface
界面:
template <typename P>
class Surface {
public:
virtual int distance(const P& from, const P& to) const = 0;
virtual bool check(const vector<P>& path, const P& from, const P& to) const = 0;
virtual vector<P> lookAround(const P& at) const = 0;
};
这里我创建一个简单的PlanarSurface
:
class PlanarSurface : public Surface<pair<int, int>> {
public:
using point_type = pair<int, int>;
int distance(const point_type& from, const point_type& to) const override {
return to.first - from.first + to.second - from.second;
}
bool check(const vector<point_type>& path,
const point_type& from,
const point_type& to) const override {
return true; // there would be the check
}
vector<point_type> lookAround(const point_type& at) const override {
vector<point_type> result;
//...
return result;
}
};
现在我创建一个抽象 class Robot
这样每个 user-implemented 机器人都会扩展它:
template <typename P>
class Robot {
public:
Robot(const Surface<P>& s): surface(s) {}
vector<P> findPath(const P& from, const P& to) {
auto path = searchPath(from, to);
if (surface.check(path, from, to)) {
return path;
}
throw runtime_error("path not found or incorrect");
}
private:
virtual vector<P> searchPath(const P& from, const P& to) = 0;
protected:
const Surface<P>& surface;
};
searchPath
私有方法将负责自定义搜索算法,定义在 Robot
的 children 中。
假设我有一个:
template <typename P>
class MyRobot: public Robot<P> {
public:
MyRobot(Surface<P> m): Robot<P>(m) {}
private:
vector<P> searchPath(const P& from, const P& to) override {
vector<P> result;
// ...
// use one of surface's virtual methods
auto dist = this->surface.distance(from, to); // Pure virtual function called!
cout << dist << endl;
// ...
return result;
}
};
最后是 main
函数:
int main(const int argc, const char **argv) {
PlanarSurface plane;
MyRobot<pair<int, int>> robot(plane);
robot.findPath({1,2}, {3,4});
return 0;
}
所以问题是,由于对 surface
的引用存储在基 Robot
class 中,我们无法用 Surface
的某些派生来指定它的类型 class。所以引用的类型只能是Surface<P, M>
.
我们需要在 Robot
的每个 child 的搜索算法中使用 surface
的 distance
和 lookAround
方法。但在 Surface<P, M>
它们是纯虚拟的。而且只能在children of Surface<P, M>
.
请帮帮我!也许我错过了一些明显的东西..
错误在这里:
MyRobot(Surface<P> m) : Robot<P>(m) {}
^^^^^^^^^^^^ value
改为接受引用
MyRobot(Surface<P>& m) : Robot<P>(m) {}
有趣的是,MSVC 和 gcc 都根据
诊断这个问题invalid abstract parameter
虽然 clang 甚至没有对此发出警告(在撰写本文时 post - 4.0)