在另一个类的构造函数中使用一个类作为参数
问题描述:
我读了关于Rcpp中的类和模块的这个blog post,我尝试重新创建它,但是我遇到了麻烦。在另一个类的构造函数中使用一个类作为参数
下面是从后代码的缩写版本:
#include <Rcpp.h>
using namespace Rcpp;
class Point {
public:
Point(double x_, double y_) : x(x_), y(y_){}
double x, y ;
} ;
class Shape {
public:
Shape(const Point& center_) : center(center_){}
Point center ;
virtual double area() const { return 0.0 ;}
virtual bool contains(const Point& point) const { return false ; }
} ;
RCPP_MODULE(play){
class_<Point>("Point")
.constructor<double,double>()
.field("x", &Point::x)
.field("y", &Point::y)
;
class_<Shape>("Shape")
.constructor<Point>()
.method("area", &Shape::area)
.method("contains", &Shape::contains)
;
};
所有这一切都发生在这里是Point类创建,然后用作Shape类的构造函数的参数。但是Shape类不会接受Point类作为构造函数中的参数。当我编译上面的代码,我得到错误:没有匹配函数调用“Point :: Point(SEXPREC * &)”。我相信这个错误是说Shape的构造函数不知道如何处理Point类。
我已经阅读了关于模块的Springer Rcpp
教科书中的章节,并且我读了关于模块的小插曲,但我不相信他们中的任何一个都有例子,其中的类是从上面的博客文章中的其他类构建的。我必须误解某些东西,所以如果有人能够启发我,我将不胜感激。
问候
答
我不知道究竟为什么在博客中的代码是(大概)有效,当它被写,不再编译,但那是大约三年前,和一些变化到Rcpp的Modules组件已经发生。要获得此代码编译,你可以在你的类定义之前添加以下内容:
class Point; // fwd declarations
class Shape;
class Circle;
class Rectangle;
RCPP_EXPOSED_CLASS(Point);
RCPP_EXPOSED_CLASS(Shape);
RCPP_EXPOSED_CLASS(Circle);
RCPP_EXPOSED_CLASS(Rectangle);
我把完整的代码从罗曼的C++为例(见下图,有几个小的修改),只是为了方便是能够运行R代码里面也包含在博客文章:
origin <- new(Point, 0, 0)
pie <- new(Circle, origin, 3)
##
R> pie$area()
#[1] 28.27433
R> pie$contains(new(Point, 1, 2))
#[1] TRUE
##
rec <- new(Rectangle, origin, 2, 3)
R> rec$area()
#[1] 6
R> rec$contains(new(Point, 1, 2))
#[1] FALSE
的完整代码(你的编译器会抱怨没有一个virtual
析构函数):
#include <Rcpp.h>
class Point; // fwd declarations
class Shape;
class Circle;
class Rectangle;
RCPP_EXPOSED_CLASS(Point);
RCPP_EXPOSED_CLASS(Shape);
RCPP_EXPOSED_CLASS(Circle);
RCPP_EXPOSED_CLASS(Rectangle);
class Point {
public:
Point(double x_, double y_) : x(x_), y(y_){}
double x, y ;
} ;
double square(double x) {
return x*x ;
}
double distance(const Point& p1, const Point& p2){
return sqrt(square(p1.x - p2.x) + square(p1.y - p2.y)) ;
}
class Shape {
public:
Shape(const Point& center_) : center(center_){}
virtual ~Shape() {}
Point center ;
virtual double area() const { return 0.0 ;}
virtual bool contains(const Point& point) const { return false ; }
} ;
class Circle : public Shape {
public:
Circle(Point center_, double radius_): Shape(center_), radius(radius_){}
double area() const {
return PI * square(radius) ;
}
bool contains(const Point& point) const {
return distance(point, center) < radius ;
}
double radius ;
} ;
class Rectangle : public Shape {
public:
Rectangle(Point center_, double width_, double height_) :
Shape(center_), width(width_), height(height_){}
double area() const {
return width * height ;
}
bool contains(const Point& point){
return (point.x >= (center.x - width/2.0)) &&
(point.x <= (center.x + width/2.0)) &&
(point.y >= (center.y - height/2.0)) &&
(point.y <= (center.y + height/2.0));
}
double width, height ;
} ;
RCPP_MODULE(play){
using namespace Rcpp;
class_<Point>("Point")
.constructor<double,double>()
.field("x", &Point::x)
.field("y", &Point::y)
;
class_<Shape>("Shape")
.constructor<Point>()
.method("area", &Shape::area)
.method("contains", &Shape::contains)
;
class_<Circle>("Circle")
.derives<Shape>("Shape")
.constructor<Point,double>()
.field("r", &Circle::radius)
;
class_<Rectangle>("Rectangle")
.derives<Shape>("Shape")
.constructor<Point,double,double>()
.field("h", &Rectangle::height)
.field("w", &Rectangle::width)
;
};
谢谢!后续问题:我如何为结构做同样的事情?我需要声明'struct myStruct;'然后执行'RCPP_EXPOSED_CLASS(myStruct);'还是有不同的宏来暴露结构? – Carl
相同的宏('RCPP_EXPOSED_CLASS')应该可以很好地用'struct'工作。就我可以告诉宏只需要'class' /'struct'的名称来生成必要的样板代码('wrap '和'')来说明。 – nrussell