在另一个类的构造函数中使用一个类作为参数

在另一个类的构造函数中使用一个类作为参数

问题描述:

我读了关于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) 
    ; 

}; 
+0

谢谢!后续问题:我如何为结构做同样的事情?我需要声明'struct myStruct;'然后执行'RCPP_EXPOSED_CLASS(myStruct);'还是有不同的宏来暴露结构? – Carl

+1

相同的宏('RCPP_EXPOSED_CLASS')应该可以很好地用'struct'工作。就我可以告诉宏只需要'class' /'struct'的名称来生成必要的样板代码('wrap '和'')来说明。 – nrussell