将带有指向另一个对象的对象写入ASCII文件(C ++)

时间:2016-03-01 17:40:41

标签: c++ pointers output fstream

我正在制作一个跟踪不同员工的计划。一些员工有合作伙伴(妻子和丈夫),因此所有员工对象都有一个名为"合作伙伴*合作伙伴" (指向Partner对象的指针)。

当我想将一个Employee写入文件时,我的问题出现了。我可以成功地将所有员工数据(姓名,地址,出生日期等)写入文件,但我不知道如何将合作伙伴写入文件。我在Partner类中有一个名为" writeToFile"的函数。输出所有合作伙伴数据,但我不知道如何连接"它到正确的Employee对象。我试图将" partner" -object输出到文件的末尾,但这只是添加了一堆零。

我应该使用两个单独的文件(一个用于员工,一个用于合作伙伴),还是应该将合作伙伴数据附加到员工数据?读回来时不会弄乱文件结构,因为只有部分员工有合作伙伴而某些合作伙伴对象只指向NULL?

我的类相互继承,因此Partner和Employee类都继承了Adult类,后者再次继承了Person类。

任何人都可以给我一个"指针"编写一个指向其中另一个对象的指针的最佳方法是什么?这是我的临时代码btw,如果有任何兴趣:

#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);
        }

1 个答案:

答案 0 :(得分:0)

除了程序的单次运行之外,指针是没有意义的,如果指针处于值has gone out of scope,则在读取文件时很可能没有意义。同一Partner存在于内存中相同位置的几率,假设空间已被分配给它,下一次可能与18,446,744,073,709,551,616中的1一样糟糕,并且错误通常会导致致命的结果。那些致命的结果意味着你很幸运。你可以粉碎属于其他东西的完全有效的内存,并导致行为奇怪,未定义,并且比直接崩溃更难调试。

在C ++中,指针往往是一个糟糕的赌注。使用它们作为最后的手段,因为它们可以真正增加您需要编写的代码量。

I recommend two lists(但不一定是两个文件。两个列表都可以轻松存在于一个文件中)PartnerEmployee之一。 Partner似乎不需要了解Employee,所以请先省去一些麻烦,然后先写下并阅读合作伙伴列表。

在撰写Employee列表时,请不要存储Partner指针,因为它无法正常工作。而是将Partner的索引存储在Partner列表中。然后,当您阅读Employee列表时,您可以在Partner表格中查看Partner的位置,查看Partner,并指向它们。这就是为什么首先编写和阅读Partner更容易的原因;很难在尚未阅读的列表中查找数据。

或完全抛弃Partner指针的概念,并始终使用索引来查看Partner。这是一种更安全的方法,只要你总是将新的合作伙伴添加到列表中,并且永远不会插入列表或做一些愚蠢的事情,就像洗牌一样。

虽然我们正在弄乱指针,但请仔细阅读&#34; What is The Rule of Three?&#34;因为你正在陷入记忆管理大屠杀的泥潭。

正如每次复制Employee时所写的那样,您将获得另一个被愚蠢复制的Employee。它复制指针而不是内容,因此您现在有2个Employee个对象指向相同的namePartner s。当你释放分配给partnernamewhich you don't and really, really should的内存时,另一个副本指向你的程序不再拥有的内存,并成为一个等待崩溃的定时炸弹你的计划。

使用std::vector<Partner>(请注意它是vector的{​​{1}},而非Partner。这允许Partner *拥有并管理所有内存对于你而不仅仅是列表所需的内存)和索引清除了vector的问题,因为Partner为你管理内存,但名称仍在等待杀死程序。用std::vector替换char *将解决这个问题,同样也可以将内存管理负担从代码移到std::string,在那里它是在20世纪90年代为你编写的,并且已经在从那以后在数百万个程序中使用。 20年后没有多少虫子可以绊倒。

如果必须使用指针和指针数组,则需要创建自定义析构函数,复制构造函数,移动构造函数,赋值运算符和移动运算符。这是一项额外的工作。

但是那些std::stringvector包含指针,你必须小心处理它们。这个主题序列化在其他地方被打死了,so here's a link to a reputable site that can probably handle it better than I can