我有两个类,在示例中添加了Rectangle和Rectangles。目标是制作一个Rectangles对象,其中包含对多个Rectangle对象的引用。
如果我改变r
通过r.set_values(4,4)
随后关闭粗r.area()
改变。但是,如果我称它为rectangles.rects[0].area()
12,则不会更改。
据我了解,我正在引用r
in rectangles
,但是这似乎是错误的。
如何实现呢?
该代码在这里可用
#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
您的代码出了什么问题是您对的定义Rectangles
。它存储指向的指针(或数组)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::vector
的erase
同时,也会破坏你的对象。因此,如果以后访问它,将会得到一些肮脏的错误。
std::shared_ptr
保留对象的共享所有权。当然,您可以对对象有另一个引用,但是如果销毁指针,也会发生相同的情况。而且,它有一些开销,并且使用起来不那么容易。
std::weak_ptr
与配合使用std::shared_ptr
,仅此而已。
相反,原始指针只需要确保对象的生存期长于或等于其自身的生存期,这样您就可以始终通过指针访问对象。仅此而已。
- unique_ptrs是唯一拥有权
- 原始指针意味着给我原始指针的任何人都可以保证该对象的生存期达到或超过我的生存期。
- shared_ptrs用于共享所有权
- 当系统想要在使用对象之前检查该对象是否仍然存在时,weak_ptrs适用于该对象。这在我的代码中很少见,因为我发现它更清洁,可以使系统保证通过其子系统的所有内容的生命周期(在这种情况下,我使用原始指针)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句