Как назначить изменяемый размер массива внутри класса в C ++

0

Мне нужно сделать размер массива, определенный внутри класса, как зависящее от ситуации значение. Чтобы пояснить суть, следующий код с фиксированным размером массива не показывает ошибки

class CMinimalServer : public GBDataAccess
{
public:
    DWORD IdG[30];
    VARIANT Value[30];
    WORD Quality[30];
    FILETIME Timestamp[30], ft;
    HRESULT Error[30];

Но мне нужно сделать размер массива, который в этом случае равен 30, в качестве надежного значения. Под этим я хочу сказать, что предположим, что в другой части кода у меня есть

if (a==b)
     Number = 10;
else
     Number = 30;

Размер массива должен быть соответственно 10 и 30.

Но следующий код показывает ошибку

class CMinimalServer : public GBDataAccess
{
public:
    DWORD IdG[Number ];
    VARIANT Value[Number ];
    WORD Quality[Number ];
    FILETIME Timestamp[Number ], ft;
    HRESULT Error[Number ];

Я пытался

#define Number 16

наверху, а приведенный выше код не показал ошибки, но проблема в том, что я не могу изменить переменную в другой части кода

////Некоторые проблемы в решении

Я изменил код в соответствии с предложением: мне нужно делать функции внутри класса (createTag).

// Class definition 
class CMinimalServer : public GBDataAccess
{
public:
struct Entry
{
    DWORD IdG;
    VARIANT Value;
    WORD Quality;
    FILETIME Timestamp;
    HRESULT Error;

};

 private:
    FILETIME ft;

 void createTag()
 {
    DWORD ids[NumberOfPoints],i;
    VARIANT val;
    val.vt = VT_BOOL;

    unsigned c=0;

    for (i = 0; i<NumberOfPoints; i++)
    {
        wchar_t opcid[NumberOfPoints];
        wsprintfW(opcid, L"Item%02i", i+1); 
        val.boolVal = VARIANT_FALSE; 
        srv.GBCreateItem(&ids[i], i, opcid, OPC_READABLE|OPC_WRITEABLE, 0, &val);
        Entry.IdG[c] = ids[i]; 
        Value[c].vt= VT_BOOL; 
        c++;
    }
.....
}

//Main function
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int   nShowCmd)
{
    CMinimalServer() = default;
CMinimalServer(int number) : tab_(number){};
std::vector<Entry> tab_ = std::vector<Entry>(30);
}

Проблемы:

  1. Как определить векторный массив idG внутри функции CreateTag.

Ошибка Entry.idG [c].

  1. "NumberOfPoints" в цикле функции createTag также равно 30. Как назначить это значение в основной функции.
  2. Как сделать еще один идентификатор массива векторов. могу ли я определить его в одной записи структуры и вызвать его в createTag.
  • 2
    Почему бы не использовать std::vector ?
Теги:
class
arrays

5 ответов

9

У нас есть вектор в C++

#include <vector>
class CMinimalServer : public GBDataAccess {
public:
    struct Entry {
        DWORD IdG;
        VARIANT Value;
        WORD Quality;
        FILETIME Timestamp;
        HRESULT Error;
    };  

    CMinimalServer() = default;
    CMinimalServer( int number ) : tab_(number) {};

private:
    FILETIME ft;
    std::vector<Entry> tab_ = std::vector<Entry>(30);
};

Разумеется, вы можете использовать вектор для каждого отдельного значения, если они вам нужны, и доступ к базовому указателю с помощью variable.data()

  • 0
    Да, это было уже по вектору в CMinimalServer, еще не проснулся полностью ^^
  • 0
    Разве в вашей структуре Entry не должно быть векторов для каждого члена для репликации образца OP? Или вообще не указывать, и заменить массивы на std::vector<> .
Показать ещё 6 комментариев
1

Если number должен быть определен во время выполнения, то решение этой проблемы заключается в определении вашего класса, как:

    class CMinimalServer : public GBDataAccess
    {
    public:
        DWORD* IdG;
        VARIANT* Value;
        WORD* Quality;
        FILETIME* Timestamp;
        FILETIME ft;
        HRESULT* Error;

        CMinimalServer(int number)
        {
             IdG = new DWORD[number];
             Value = new VARIANT[number];
          ... etc
        }

        ~CMinimalServer()
        {
             delete[] IdG;
             delete[] Value;
           ... etc
        }
   }
  • 0
    Вы не должны показывать голый указатель, так как это плохая привычка, по крайней мере, используйте умный указатель, такой как unique_ptr.
  • 2
    @ galop1n Умные указатели не панацея; в этом случае он должен использовать std::vector , а не указатели. Но если он собирается использовать указатели: в этом случае они должны быть умными указателями. Код, как написано, утечки памяти (и, следовательно, является неправильным).
0

ISO не допускает массив переменной длины. Однако есть лазейка. Вы можете создать массив с переменной как ее размер во время выполнения с использованием динамической памяти.

Например: int x = 4; int * a = new int [x];

Не забудьте использовать delete!

delete [] a;

Надеюсь, это поможет!

0

Если вам нужен массив независимых значений const compimeime, используйте std: vector.

  • 0
    Будучи технически правильным, это худший ответ среди всех остальных здесь!
  • 0
    @ πάνταῥεῖ На самом деле, это единственный, который является правильным.
Показать ещё 1 комментарий
-2

Отредактировано: от голых указателей до общих указателей,

Динамическое выделение памяти с помощью указателей сделает это,

class CMinimalServer : public GBDataAccess
{
public:
 shared_ptr<DWORD> IdG;
 shared_ptr<VARIANT> Value;
 shared_ptr<WORD> Quality;
 shared_ptr<FILETIME> Timestamp, ft;
 shared_ptr<HRESULT>* Error;

Затем внутри конструктора присвойте им память (определите размер массива), как это

CMinimalServer::CMinimalServer()
{
  IdG = new DWORD(Number);
  Value = new VARIANT(Number);
  Quality = new WORD(Number);
  Timestamp = new FILETIME(Number);
}
  • 1
    Вы не должны показывать голый указатель, так как это плохая привычка, по крайней мере, используйте умный указатель, такой как unique_ptr .
  • 2
    new DWORD(Number) Это совершенно неправильно, если вы хотите выделить массив, используйте new DWORD[Number] ... И нет смысла использовать массивы в этом контексте, когда возможно использовать std :: vector, особенно поскольку существует необходимость динамически расширять массивы.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню