«Явный» тип в Java - это класс, который является неэквивалентным и имеет дело с «сырыми» объектами, а не с типичными типами типовых параметров.
Например, до того, как были доступны дженерики Java , вы должны использовать класс коллекции следующим образом:
LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);
Когда вы добавляете свой объект в список, ему все равно, какой тип объекта он есть, и когда вы его получите из списка, вам нужно явно указать его на тот тип, который вы ожидаете.
Используя generics, вы удаляете «неизвестный» коэффициент, потому что вы должны явно указать, какой тип объектов может идти в списке:
LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);
Обратите внимание, что с помощью дженериков вам не нужно бросать объект, исходящий из вызова get, сбор предварительно задан для работы с MyObject. Этот факт является основным движущим фактором для генериков. Он меняет источник ошибок времени выполнения во что-то, что можно проверить во время компиляции.
Файл для чтения был открыт только для записи.
Фактический объект std::string
не может быть записан таким образом. Фактический объект обычно содержит пару указателей и, возможно, размер, но не фактические данные символов.
Если вы собираетесь писать C ++, вам следует подумать об использовании файловых потоков, а не о том, что у вас здесь.
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <string>
#include <vector>
typedef struct s_test
{
char cmd[5];
std::string str;
}t_test;
void Write(int fd, struct s_test* test)
{
write(fd, test->cmd, sizeof(test->cmd));
unsigned int sz = test->str.size();
write(fd, &sz, sizeof(sz));
write(fd, test->str.c_str(), sz);
}
void Read(int fd, struct s_test* test)
{
read(fd, test->cmd, sizeof(test->cmd));
unsigned int sz;
read(fd, &sz, sizeof(sz));
std::vector<char> data(sz);
read(fd, &data[0], sz);
test->str.assign(data.begin(), data.end());
}
int main()
{
t_test test;
int fd = open("test", O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, 0666);
test.cmd[0] = 's';
test.cmd[1] = 'm';
test.cmd[2] = 's';
test.cmd[3] = 'g';
test.cmd[4] = 0;
test.str = "hello world";
std::cout << "Before Write: " << test.cmd << " " << test.str << std::endl;
Write(fd, &test);
close(fd);
fd = open("test", O_RDONLY, 0666);
t_test test2;
Read(fd, &test2);
std::cout << "After Read: " << test2.cmd << " " << test2.str << std::endl;
close(fd);
return (0);
}
См., когда вы выгружаете структуру в двоичный файл, ее изображение в памяти записывается на диск, например:
class X
{
public:
int i;
int j;
};
. , .
X lX;
lX.i= 10;
lX.j = 20;
объект класса lX при записи в двоичный файл будет выглядеть примерно так: | 10 | 20 | i.e, когда вы его прочитаете, он будет работать нормально.
, но для класса, который содержит любой указатель, такой как строка.
class Y
{
public:
int* pi;
int j;
};
. , .
Y lY;
lY.pi= new int(10); // lets assume this is created at memory location 1001
lY.j = 20;
, поэтому объект lY будет иметь значение pi как 1001 (не 10, так как это указатель). теперь, когда вы пишете lY в двоичном файле, это будет выглядеть как | 10001 | 20 | и когда вы его прочитаете, он построит новый объект Y (скажем, lY2), имеющий значения pi, равные 1001, а j - 20. Теперь мы указываем на то, что pi (которое является указателем)? ответ - мусор, это то, что вы смотрите на экране. Я думаю, вы используете Windows для запуска этого, так как Linux дал бы вам ошибку сегментации.