2014-09-03 29 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

相關問題