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

时间:2015-11-05 16:22:09

标签: r rcpp

我读了这篇关于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 *&amp;)”的匹配函数。我相信这个错误是说Shape的构造函数不理解如何处理Point类。

我已经阅读了关于模块的Springer Rcpp教科书中的章节,我阅读了关于模块的小插图,但我不相信其中任何一个都有例子,其中类是从其他类构建的,如上所述博客文章。我一定是在误解,所以如果有人能够启发我,我会很感激。

此致

1 个答案:

答案 0 :(得分:4)

我不确定完全为什么该博客文章中的代码(大概)在编写时已经有效并且不再编译,但大约三年前,有些自那时起,对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);

我从Romain的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中没有Shape析构函数时抱怨:

#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 )
  ;

};