2015-11-05 315 views
3

我讀了關於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教科書中的章節,並且我讀了關於模塊的小插曲,但我不相信他們中的任何一個都有例子,其中的類是從上面的博客文章中的其他類構建的。我必須誤解某些東西,所以如果有人能夠啓發我,我將不勝感激。

問候

回答

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

我把完整的代碼從羅曼的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

相關問題