Сейчас я изучаю C++ и пытаюсь создать vector
собственный тип данных Employee
.
Код сотрудника.h:
public ref class Employee {
public:
System::String^ name;
int age;
Employee() {
name = "";
age = 0;
}
Employee(System::String^ n, int a) {
name = n;
age = a;
}
};
Код сотрудника.cpp:
#include "Employee.h"
#include <string>
int main() {
std::vector<Employee^> employees;
employees.push_back(gcnew Employee("Alice", 20));
employees.push_back(gcnew Employee("Bob", 22));
return 0;
}
Когда меня попытались инициализировать vector<Employee>
в MyForm.h, вот так:
private: std::vector<Employee^> Employees;
Возникает ошибка "^": E2244 член управляемого класса не может принадлежать к типу неуправляемого класса.
Я пробовал использовать разные указатели, а также создавать конструктор копирования для класса Сотрудник (пытался найти подобные ситуации у других людей), но это приводило к еще большему количеству ошибок. Возможно, ошибка тривиальна и проста, но, к сожалению, у меня мало времени погружаться в теорию. Что я делаю не так и как это исправить? Буду очень рад, если объясните подробно.
Используйте C++/CLI (т. е. .NET) List<Employee^>
(System::Collections::Generic::List<Employee^>
). std::vector
— для неуправляемых классов.
@wohlstad Я решил попробовать сделать это с помощью вектора, потому что это более удобный способ доступа к элементам. Я, конечно, попробую воспользоваться списком, но не думаю, что это будет лучшим решением. Я думаю, что «набор» имеет ту же ситуацию, что и вектор в командной строке?
В качестве альтернативы хорошему предложению @wohlstad можно использовать STL/CLR cliext::vector<> для полного сохранения семантики значений.
@ildjarn Забавно, но я пытался использовать cliext::vector, но получил аналогичную ошибку...
Вы, должно быть, ошибаетесь: в cliext::vector<Employee>
нет неуправляемых типов, поэтому ошибка не может быть такой похожей...
C++ и C++/CLI — разные языки:
C++/CLI — это .NET-версия собственного C++.
Вы не можете использовать собственный контейнер C++, такой как std::vector
, для хранения объектов .NET, подобных вашему Employee
.
Вместо этого вам следует использовать контейнер C++/CLI (т.е. .NET).
Одним из таких кандидатов является System::Collections::Generic::List, поскольку он чем-то похож на std::vector
, с непрерывной структурой памяти для элементов и произвольным доступом к ним.
В вашем случае это будет:
System::Collections::Generic::List<Employee^> ^ employees =
gcnew System::Collections::Generic::List<Employee^>();
employees->Add(gcnew Employee("Alice", 20));
employees->Add(gcnew Employee("Bob", 22));
Последний пример весьма неидиоматичен – cliext::vector<Employee^>^
сродни std::vector<Employee*>*
и, откровенно говоря, никто бы никогда этого не сделал. Смысл STL/CLR заключается в использовании семантики значений, такой как C++, поэтому нельзя помещать тип дескриптора в ссылку ни в один из его контейнеров (и, вероятно, не следует gcnew
и сам контейнер, если только он не сохранил множество %
позже в функции). См. Семантика стека C++ для ссылочных типов
@ildjarn точка зрения принята - спасибо. Поскольку я не совсем знаком с STL/CLR, я удалю последний пример и оставлю тот, с которым я сейчас знаком. Я прочитаю об этом больше позже.
C++ и C++/CLI — это не одно и то же. Ошибки, начинающиеся с
E
, являются интеллектуальными. Скомпилируйте программу и получите ошибку, начинающуюся сC
.