c ++将对象存储到该对象的构造函数中的对象数组中

时间:2014-09-14 22:17:23

标签: c++ class object

我正在尝试创建一个对象,每次创建一个对象时,我都会将该对象存储在一个静态类变量中,该变量是所有创建的对象的数组。

我是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
}

这可能吗?

2 个答案:

答案 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个想法: