简体   繁体   中英

Trying to create a class that contains an array of structs, that are predefined

I have a class called CoolMenuItems

class CoolMenuItems
{
public:
    CoolMenuItems();
    ~CoolMenuItems();

    struct MenuItemOne
    {
        int id;
        uint32 type;
        uint32 subtype;
        String name;
    };

    struct MenuItemTwo
    {
        uint32 subtype;
        String name;
    };
}

This is just the bare bones of the class... I want to have two arrays, one of MenuItemOne, and one of MenuItemTwo, and these arrays would have the following. These arrays I want to initialize like:

MenuItemOne a[] =
{
    {1, EQData::EQ_EFFECT_TYPE_PARAMETRIC,       0,                                              T("Parametric")},
    {2, EQData::EQ_EFFECT_TYPE_FILTER_LOW_PASS,  EQData::EQ_FILTER_TYPE_FILTER_BUTTERWORTH_12DB, T("Low Pass")},
};

MenuItemTwo b[] =
{
    {EQData::EQ_FILTER_TYPE_TRHU,                      T("Thru")},
    {EQData::EQ_FILTER_TYPE_BUTTERWORTH_6DB,           T("6  dB Butterworth")},

};

only, with more elements than just two...

I want to set it up so that I can create a new CoolMenuItems object with

CoolMenuItems *cmi = new CoolMenuItems();

so that I can access those array elements via

cmi->a[1];

Initialization of member variables are somewhat tricky in C++, so my recommendation would be something like the following:

MenuItemOne& ret_a(int i)
{
    static MenuItemOne a[] =
    {
        // definition of a[]
    };
    return a[i]; // maybe with some bounds checking
}

Note that this has some advantages. First, declaring the array a as static inside a class method makes it globally defined just once. Second, you hide the actual a[] array behind a method call, which is a better design practice.

EDIT

As the arrays cannot be static, as the values depend on some other library, the values have to be set up at some point, say the CoolMenuItems constructor:

CoolMenuItems::CoolMenuItems()
{
    for (int i = 0; i < A_ITEMS; ++i)
    {
       a[i].id = X;
       a[i].name = T("xxx");
    }   
    // ...
}

or, if you have to put the values by hand:

CoolMenuItems::CoolMenuItems()
{
    a[0].id = X;
    a[0].name = T("xxx");
    a[1].id = ...   
    // ...
}

This is tedious, but can be automated with some editor usage, or preprocessor. Note also that you then have to declare the ret_a function similarly and declare the corresponding a and b arrays within the class:

MenuItemOne a[A_ITEMS];
MenuItemTwo b[B_ITEMS];

With enough time, I'd give you a nice elisp macro to be used within emacs to generate all the initializations from the C arrays you wrote:)

Can you modify your code like this

class CoolMenuItems
{
public:
    CoolMenuItems();
    ~CoolMenuItems();

    struct MenuItemOne
    {
        int id;
        uint32 type;
        uint32 subtype;
        String name;
    };

    struct MenuItemTwo
    {
        uint32 subtype;
        String name;
    };
std::vector<MenuItemOne> menuItemOne;
std::vector<MenuItemTwo> menuItemTwo;
}

So that you can initialize the elements of struct and push_back the struct into the std::vector, all the memory to be allocated and to be freed will be taken care of by the std::vector

MenuItemOne a = {1, EQData::EQ_EFFECT_TYPE_PARAMETRIC, 0,T("Parametric")};

menuItemOne.push_back(a);

Similarly for MenuItemTwo. If you have a different requirement then please give more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM