2015-11-05 3 views
3

Я прочитал это blog post о классах и модулях в Rcpp, и я попытался его воссоздать, но у меня проблемы.Использование класса в качестве параметра в конструкторе другого класса

Вот сокращенный вариант кода с поста:

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

}; 

Все, что здесь происходит, класс создается точка, а затем используется в качестве параметра в конструктор класса Shape. Но класс Shape не будет принимать класс Point в качестве параметра в конструкторе. Когда я компилирую вышеуказанный код, я получаю ошибку: никакой подходящей функции для вызова «Point :: Point (SEXPREC * &)». Я считаю, что эта ошибка говорит о том, что конструктор для Shape не понимает, как обращаться с классом Point.

Я прочитал главу в учебнике Springer Rcpp о модулях, и я прочитал виньетку об модулях, но я не верю, что в любом из них есть примеры, когда классы создаются из других классов, как в приведенном выше сообщении блога. Я должен что-то недопонимать, поэтому я был бы признателен, если бы кто-нибудь мог просветить меня.

С уважением

ответ

4

Я не уверен, точно почему код в этом блоге было (предположительно) действует, когда она была написана, и больше не компиляции, но это было примерно три года назад, и некоторые изменения к компоненту модулей Rcpp с тех пор. Для того, чтобы получить эту компиляцию, вы можете добавить следующее перед вашими определениями классов:

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 деструктора в 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) 
    ; 

}; 
+0

Спасибо! Последующий вопрос: как бы я сделал то же самое для структур? Должен ли я объявить «struct myStruct;», а затем сделать «RCPP_EXPOSED_CLASS (myStruct)» или существует другой макрос для раскрытия структур? – Carl

+1

Тот же макрос ('RCPP_EXPOSED_CLASS') должен отлично работать с' struct'. Насколько я могу судить, макросу просто нужно имя 'class' /' struct' для генерации необходимого шаблона кода ('wrap <>' и 'as <>') для изложения. – nrussell