2014-09-03 65 views
0

我有两个类,在示例中添加了Rectangle和Rectangles。目标是使一个Rectangles对象保存对多个Rectangle对象的引用。如何在C++中的类之间保持多个引用?

如果我更改rr.set_values(4,4)然后关闭粗r.area()被更改。但是,如果我拨打rectangles.rects[0].area(),它仍然是12,因此不会更改。

据我所知,我在rectanglesr的参考,但是这似乎是错误的。

如何实现这一目标?

的代码可以here

#include <iostream> 

using namespace std; 

class Rectangle { 
    int width, height; 
    public: 
    void set_values (int,int); 
    int area() {return width*height;} 
}; 

void Rectangle::set_values (int x, int y) { 
    width = x; 
    height = y; 
} 


class Rectangles { 
    public: 
    Rectangles(int n); 
    void addRectangle(Rectangle* r); 
    Rectangle* rects; 
    int nRects; 
}; 

Rectangles::Rectangles(int n) { 
    rects = new Rectangle[n]; 
    nRects = 0; 
} 

void Rectangles::addRectangle(Rectangle* r) { 
    rects[nRects] = *r; 
    nRects++; 
} 


int main() { 
    Rectangle r; 
    Rectangles rectangles(5); 
    r.set_values(4,3); 

    rectangles.addRectangle(&r); 

    cout<<"r.area() before change:"<<r.area()<<endl; 
    cout<<"rectangles.rects[0].area() before change:"<<rectangles.rects[0].area()<<endl; 

    r.set_values(4,4); 

    cout<<"r.area() after change:"<<r.area()<<endl; 
    cout<<"rectangles.rects[0].area() after change:"<<rectangles.rects[0].area()<<endl; 

    return 0; 
} 

输出:

r.area() before change:12 
rectangles.rects[0].area() before change:12 
r.area() after change:16 
rectangles.rects[0].area() after change:12 
+1

没有寿命,你是不是保持在基准'Rectangles',你*复制'Rectangle'对象。如果你想要一个引用集合,我建议你阅读['std :: vector'](http://en.cppreference.com/w/cpp/container/vector)和['std :: shared_ptr']( http://en.cppreference.com/w/cpp/memory/shared_ptr)。 – 2014-09-03 08:52:04

+0

@JoachimPileborg好的,我应该如何改变这段代码,让我保持引用? – Nick 2014-09-03 08:54:01

回答

1

什么是你的代码错误是你的定义。它将指针(或数组)存储到Rectangle。你在这里想要的不是Rectangle的数组,而是的参数Rectangle的数组。在这里,引用应是指针,所以需要相应地改变这种:

class Rectangles { 
    public: 
    Rectangles(int n); 
    void addRectangle(Rectangle* r); 

    // Rectangle* rects; 
    // What you really want : 
    Rectangle** rects; 

    int nRects; 
}; 

但你还需要更改实施:

Rectangles::Rectangles(int n) { 
    rects = new Rectangle*[n]; // Array of pointers 
    nRects = 0; 
} 

void Rectangles::addRectangle(Rectangle* r) { 
    rects[nRects] = r; // r is a pointer : just store it, no dereferencing 
    nRects++; 
} 

然而,这是一个不好的设计:你不应该使用下面的任何一个:指向指针的指针(或指针的'原始数组'),new,以及一个只存储一组事物的类。这是因为你已经有了更好的工具:智能指针(尽管你不需要它们),数组和动态数组(或向量)。

所以,如果我是你,我这是怎么会重写代码:

#include <iostream> 
#include <vector> 

class Rectangle { 
public: 
    void setSize(int w, int h); 
    int area(); 

private: 
    int width, height; 
}; 

void Rectangle::setSize(int w, int h) { 
    width = w; 
    height = h; 
} 

int Rectangle::area() { 
    return width * height; 
} 

int main() { 
    Rectangle r; 
    std::vector<Rectangle*> rectangles; 
    r.setSize(4, 3); 

    rectangles.push_back(&r); 

    std::cout << "r.area() before change : " << r.area() << std::endl 
       << "rectangles[0]->area() before change : " 
       << rectangles[0]->area() << std::endl; 

    r.setSize(4, 4); 

    std::cout << "r.area() after change : " << r.area() << std::endl 
       << "rectangles.rects[0]->area() after change : " 
       << rectangles[0]->area() << std::endl; 

    return 0; 
} 

编辑

你可能会问,为什么我用了一个原始指针,而不是智能指针(因为我告诉过你避免指向指针)。这很简单:没有智能指针可以解决问题。让我们看看为什么。

std::unique_ptr保留对象的唯一所有权。如果你想要另一个参考呢?另外,如果你通过std::vectorerase销毁这个智能指针,它也会破坏你的对象。所以如果你之后访问它,你会得到一些肮脏的错误。

std::shared_ptr保持对象的共享所有权。当然,你可以对你的对象有另一个引用,但是如果你销毁指针,也会发生同样的事情。此外,它有一些开销,并且不容易正确使用。

std::weak_ptrstd::shared_ptr一起使用,没什么可说的。

相反,原始指针只需要您确保对象的生命周期长于或等于其生命周期,以便始终可以通过指针访问对象。就是这样。

最后,here is a general rule of thumbs(我使用):

  • unique_ptrs是独资
  • 原始指针意味着谁给我的原始指针保证对象的生命周期相匹配或超过我的一生。
  • shared_ptrs是共享所有权
  • weak_ptrs是当系统要检查的对象使用前仍然存在。这是在我的代码罕见的,因为我觉得它更清洁有一个系统保证任何它通过它的子系统(在这种情况下,我使用的是原始指针)
1
class Rectangles { 
public: 
    void addRectangle(Rectangle* r); 
    vector<Rectangle *> rects; 
}; 

void Rectangles::addRectangle(Rectangle* r) { 
    rects.push_back(r); 
} 

int main() { 
    Rectangle r; 
    Rectangles rectangles; 
    r.set_values(4,3); 

    rectangles.addRectangle(&r); 

    cout<<"r.area() before change:"<<r.area()<<endl; 
    cout<<"rectangles.rects[0]->area() before change:"<<rectangles.rects[0]->area()<<endl; 

    r.set_values(4,4); 

    cout<<"r.area() after change:"<<r.area()<<endl; 
    cout<<"rectangles.rects[0]->area() after change:"<<rectangles.rects[0]->area()<<endl; 

    return 0; 
} 

输出:

r.area() before change:12 
rectangles.rects[0]->area() before change:12 
r.area() after change:16 
rectangles.rects[0]->area() after change:16 
+0

看起来不错,我想知道我是否可以在arduino程序中使用它。 – Nick 2014-09-03 09:07:22

+0

什么是arduino程序?只要支持C++,它应该没问题。 – Krypton 2014-09-03 09:08:27

+0

我刚刚发现,有arduino的特定库和矢量的用法。所以我可以解决这个问题。 – Nick 2014-09-03 09:17:30

相关问题