我正在尝试创建一个对象,每次创建一个对象时,我都会将该对象存储在一个静态类变量中,该变量是所有创建的对象的数组。
我是c ++的新手,不知道如何做到这一点。我以前用Java做过,但我被困在这里。
以此为例:
class Rectangle
{
private:
int width;
int length;
// Code to create an array of Rectangle Objects
// that hold all the the Rectangles ever created
public:
Rectangle();
Rectangle(int x, int y);
};
Rectangle::Rectangle()
{
width = 0;
length = 0;
// code to add an instance of this object to an array of Rectangle Objects
}
Rectangle::Rectangle(int x, int y)
{
width = x;
length = y;
// code to add an instance of this object to an array of Rectangle Objects
}
这可能吗?
答案 0 :(得分:1)
由于必须使用数组来保持所有对象都必须定义一个恒定的最大大小,因为数组的大小是固定的并且无法更改。这意味着您还必须定义一个变量来跟踪数组中有多少元素,这样就不会超出其边界。
const int MAX_SIZE = 100;
class Rectangle
{
private:
int width;
int length;
static Rectangle* all_rectangles[MAX_SIZE];
static int rectangle_count;
public:
Rectangle();
Rectangle(int x, int y);
};
然后定义静态变量并将对象添加到Rectangle构造函数中的数组中,例如:
//Define static variables
Rectangle* Rectangle::all_rectangles[MAX_SIZE];
int Rectangle::rectangle_count = 0;
//Constructor
Rectangle::Rectangle () {
all_rectangles[rectangle_count] = this;
rectangle_count++;
}
由于具有矩形(及其组件)的数组是私有的,因此您只能从类中访问它。但是,您可以定义公共函数,以达到矩形私有变量。您可以通过声明函数
来获取矩形的宽度static int getWidth(int a){
return all_rectangles[a]->width;
}
并通过cout << Rectangle::getWidth(2) // Get width of second element in array
然而,矢量最好在数组之前使用,因为它们是可扩展的,并且包含许多内置函数,例如添加和删除元素。
答案 1 :(得分:1)
现在我们倾向于避免使用普通数组和普通指针。
所以选择智能指针和STL容器。 当你的物体生存和死亡时,矢量可能不会很快稀疏,有很多洞对应你不再使用的(删除的)物体。
另一种解决方案是无序映射(哈希表)。然后我们需要一把钥匙。我们不会考虑将(this)指针的值转换为int或long,因为它是一种非常危险的方法。
所以我们必须支付一些独特的ID(参见boost uuid)。这对于计算时间来说也是昂贵的,但所有这些机制将节省您的时间(用于编写代码文档)。
然后我们需要一个智能指针。 由于您想要跟踪创建的所有对象,我们将使用强制“工厂”功能来创建对象。由于它们可能不是唯一拥有的,因此工厂函数的唯一选择是拒绝共享指针。
这不是直接存储在容器中的共享指针,因为它会阻止我们在不再需要时轻松摆脱对象(容器内的共享指针仍然会参与对象计数)。 / p>
共享指针可能会有一个自定义删除器,让我们为容器做一些内务管理
所以这是一个弱指针(不参与为我们的容器选择的对象计数(或在很小程度上(弱计数))。
这是一些代码(原谅我选择了widget而不是矩形):
我们的课程必须继承这个好奇的课程(例如参见Scott Meyers的新书Effective Modern C ++第19项)
class widget:public std::enable_shared_from_this<widget>
别名(~typedef)
using widget_weakptr_cont_t = std::unordered_map<std::string,std::weak_ptr<widget>>;
using widget_smrtp_t = std::shared_ptr<widget>;
using uuid_t = boost::uuids::uuid;
工厂功能
static widget_smrtp_t widget_factory(void);
容器
static widget_weakptr_cont_t widget_cont;
构造函数是私有的(您也可以阻止所有其他形式的复制或移动构造来强化规则)
private:
widget();
void self_emplace(void);
const uuid_t uuid_tag;
共享指针的自定义删除器
auto widgetDeleter = [](widget* pw) {
std::cout << "Widget deleter" << std::endl;
widget::widget_cont.erase(pw->uuid_to_string());
delete pw;
if ( widget::widget_cont.empty() )
std::cout << "No Widget left" << std::endl; };
工厂功能
widget::widget_smrtp_t widget::widget_factory(void)
{
auto wshp = widget_smrtp_t(new widget(),widgetDeleter);
wshp->self_emplace();
return wshp;
}
self_emplace函数
void widget::self_emplace(void)
{
widget::widget_cont.emplace(uuid_to_string(),shared_from_this());
}
然后,您可以在其他一些功能(或主要())
中使用您的工厂功能auto pw = widget::widget_factory();
从容器中检索对象的示例可以是
for ( auto const & it : widget::widget_cont )
{
//if interested by uuid we normally do
// std::cout << it.first << std::endl;
//For exercice we do the following:
auto shp = it.second.lock();
if ( shp )
{
std::cout << shp->uuid_to_string() << std::endl;
}
}
在函数func下面的执行中(这里没有显示帖子已经太长了) 只生成一个全局因子共享指针的副本(到我们的一个小部件)。 容器不会被func中发生的事情修改。
func2创建另一个在离开func2时被销毁的本地小部件。容器显示在这两个步骤。
最后,全局构建的小部件仅在(主要)
的末尾被销毁Hello world!
Widget elems are:
84871b52-0757-44c1-be23-fb83e69468c0
func
Widget elems are:
84871b52-0757-44c1-be23-fb83e69468c0
func2
Widget elems are:
b2aedb78-8bb0-427e-9ada-fce37384f7de
84871b52-0757-44c1-be23-fb83e69468c0
Widget deleter
Widget elems are:
84871b52-0757-44c1-be23-fb83e69468c0
bye !
Widget deleter
No Widget left
我希望所有这一切都有所帮助
NGI
编辑2016.08.21 我发布了“未删节代码”Code on Coliru 它不会更清楚,因为当我第一次回复时,我还尝试了其他语法功能,仅用于测试。
无论如何你现在掌握在手中(有时我不会发布完整的代码以避免“作业”复制/粘贴问题)
最近我试图简化我的代码而没有成功,2个想法: