将一个对象写入一个对象,该对象带有指向另一个对象的指针,指向 ASCII 文件 (C++)
Writing an object with a pointer to another object to an ASCII file (C++)
我正在制作一个跟踪不同员工的程序。某些员工有合作伙伴(妻子和丈夫),因此所有 Employee 对象都有一个名为"合作伙伴* 合作伙伴"的数据成员(指向合作伙伴对象的指针)。
当我想将员工写入文件时,我的问题就来了。我可以成功地将所有员工数据(姓名、地址、出生日期等)写入文件,但我不知道如何将合作伙伴写入文件。我在合作伙伴类中有一个名为"writeToFile"的函数,它输出所有合作伙伴数据,但我不知道如何将其"连接"到正确的 Employee 对象。我试图只将"partner"对象输出到文件的末尾,但这只是添加了一堆零。
我应该使用两个单独的文件(一个用于员工,一个用于合作伙伴),还是只将合作伙伴数据追加到员工数据?在读回文件时,这不会弄乱文件结构吗,因为只有一些员工有合作伙伴,而一些合作伙伴对象只指向 NULL?
我的类相互继承,因此 Partner 和 Employee 类都继承 Adult 类,后者再次继承 Person 类。
谁能给我一个"指针",说明编写一个对象的最佳方法是什么,该对象内部有一个指向另一个对象的指针?顺便说一句,这是我的临时代码,如果它有任何兴趣:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
const int MAXTXT = 80;
class Person {
protected:
char* firstname;
char birthdate[6];
public:
Person() {
char fname[MAXTXT];
cout << "First name: "; cin.getline(fname, MAXTXT);
firstname = new char[strlen(fname + 1)];
strcpy(firstname, fname);
cout << "Birth date (DDMMYY): ";
cin >> birthdate; cin.ignore();
}
void display() {
cout << "nFirst name: " << firstname;
cout << "nBorn: " << birthdate;
}
void writeToFile(ofstream & ut) {
ut << firstname << "n" << birthdate;
}
};
class Adult: public Person {
protected:
char* lastname;
public:
Adult() {
char lname[MAXTXT];
cout << "Last name: "; cin.getline(lname, MAXTXT);
lastname = new char[strlen(lname + 1)];
strcpy(lastname, lname);
}
void writeToFile(ofstream & out) {
out << "n" << lastname << "n";
}
void display() {
cout << "nLast name: " << lastname;
}
};
class Partner: public Adult {
private:
int phone1;
int phone2;
public:
Partner() {
cout << "Phone (mobile): "; cin >> phone1;
cout << "nPhone (job): "; cin >> phone2; cin.ignore();
}
void writeToFile(ofstream & out) {
Person::writeToFile(out);
Adult::writeToFile(out);
out << "n" << phone1 << " " << phone2;
}
void display() {
Person::display();
Adult::display();
cout << "nPhone (mobile): " << phone1;
cout << "nPhone (job): " << phone2;
}
};
class Employee: public Adult {
private:
int nr;
char* address;
Partner* partner;
public:
Employee() {
}
Employee(int n) {
char adr[MAXTXT];
nr = n;
cout << "Address: "; cin.getline(adr, MAXTXT);
address = new char[strlen(adr + 1)];
strcpy(address, adr);
partner = NULL;
}
void changePartner() {
Partner::Partner();
}
void writeToFile(ofstream & out) {
Person::writeToFile(out);
Adult::writeToFile(out);
out << nr << "n" << address << endl;
}
void display() {
Person::display();
Adult::display();
cout << "nAddress: " << address;
if(partner) {
partner->display();
}
}
int returnEmpNr() {
return nr;
}
};
Employee* employees[100];
int lastUsed = 0;
int main() {
}
void writeToFile() {
ofstream outfile("EMPLOYEES.DAT");
ofstream outfile2("PARTNERS.DAT");
outfile << lastUsed << "n";
for(int i = 1; i <= lastUsed; i++) {
employees[i]->writeToFile(outfile);
}
指针除了对程序的单次运行之外毫无意义,如果指针在值处超出范围,则在读取文件时很可能毫无意义。Partner
假设已经为它分配了空间,那么下一次的几率可能与 18,446,744,073,709,551,616 中的 1 一样糟糕,并且出错通常会造成致命的结果。这些致命的结果意味着你很幸运。您可能会破坏属于其他东西的完全有效的内存,并导致奇怪的、未定义的、比彻底崩溃更难调试的行为。
在C++指针通常是一个傻瓜赌注。 将它们用作最后的手段,因为它们确实可以增加您需要编写的代码量。
我推荐两个列表(但不一定是两个文件。两个列表都可以很容易地存在于一个文件中)一个是Partner
s,一个是Employee
s。Partner
似乎不需要了解Employee
,所以省去一些麻烦,先写出来并在合作伙伴列表中阅读。
编写Employee
列表时,不要存储Partner
指针,因为它不起作用。而是将Partner
的索引存储在Partner
列表中。然后当你阅读Employee
列表时,你可以读取Partner
在Partner
表中的位置,查找该Partner
,并指向它们。这就是为什么首先编写和阅读Partner
要容易得多的原因;很难在尚未读取的列表中查找数据。
或者完全抛弃Partner
指针的概念,并始终使用索引来查找Partner
。这是更安全的方法,只要您始终将新合作伙伴附加到列表中,并且永远不要插入列表或做一些愚蠢的事情,例如打乱列表。
当我们弄乱指针时,请仔细阅读"什么是三法则?",因为您正在陷入内存管理大屠杀的泥潭。
正如每次复制Employee
时所写,您将获得另一个愚蠢复制的Employee
。它复制指针,而不是内容,因此您现在有 2 个Employee
对象指向相同的 name
s 和 Partner
s。当你释放分配给partner
和name
的内存时,你没有,而且真的,真的应该,另一个副本指向你的程序不再拥有的内存,并成为一个滴答作响的定时炸弹,等待你的程序崩溃。
使用std::vector<Partner>
(注意它是Partner
的vector
,而不是Partner *
。这允许vector
拥有和管理您的所有内存,而不仅仅是列表所需的内存)和索引清除了Partner
的问题,因为std::vector
为您管理内存,但名称仍在等待终止程序。用std::string
替换char *
将解决这个问题,还可以通过将内存管理负担从代码转移到 1990 年代某个时候为您编写的std::string
,此后一直在数百万个程序中使用。20年后,没有多少虫子可以绊倒。
如果必须使用指针和指针数组,则需要创建自定义析构函数、复制构造函数、移动构造函数、赋值运算符和移动运算符。这是很多额外的工作。
但是这些vector
和string
包含指针,您必须谨慎编写它们。这个主题,序列化,已经在其他地方被打死了,所以这里有一个指向一个信誉良好的网站的链接,它可能比我更好地处理它。
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 从多个源构造一个对象,包括一个对象向量
- 为什么C++在将一个对象复制到另一个对象时需要对这两个对象进行低级常量限定
- 检查哪个对象调用了另一个对象的对象方法
- C++ 如何在将新对象分配给另一个对象时创建新对象
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 指向另一个对象的指针
- c++ 序列化包含字符串和指向另一个对象的指针的对象
- 你能对指向另一个对象的字符*进行算术吗?
- 在C++中,我如何创建一个数组,数组中大小为10的每个元素都指向一个对象
- 如何将 SHM 对象指向另一个 SHM 对象
- 销毁和重新创建一个对象会使指向该对象的所有指针无效吗
- 将一个对象写入一个对象,该对象带有指向另一个对象的指针,指向 ASCII 文件 (C++)
- 将多个指针分配给同一对象并检查地址后,只有一个指针指向正确的指针
- 成员函数指针指向另一个对象的方法
- 从另一个对象指向线程对象:危险
- 克隆一个对象,当我有一个指针指向它的基类
- C++:将指向一个对象的成员函数的指针存储在另一个对象中
- 如何返回一个指针(指向带有模板参数类型的方法中模板类型的对象)