动态对象数组不起作用

时间:2017-12-13 23:39:22

标签: c++ arrays

我有一个父项和两个孩子,我想创建一个包含子项的动态数组(不允许使用向量)。我创建了类和所有内容,并且没有编译错误或警告,但是当我尝试访问数组的成员并打印其内容时,没有任何反应。

我知道这里可能存在一些糟糕的编码风格,但我只是想知道阵列为什么不起作用。我认为这是因为我创建了一个对象数组,而不是一个指向对象的指针数组,我不确定。

(我从代码中移除了第二个孩子,因为它在这里无关紧要)

#pragma warning(disable:4996)
using namespace std;
#include <iostream>
#include <cstdlib>
#include <cctype>
#include "date.h"

#define ADDRESS_SIZE 512
#define NAME_SIZE 128
#define DATE_SIZE 128



class Treatment {
protected:
    int treatment_ID;
    int patient_ID;
    Date treatment_date;
    int treatment_costs;
public:
    Treatment() {}
    Treatment(int treatment_ID, int patient_ID, int treatment_costs, char treatment_date[DATE_SIZE]) {
        this->treatment_ID = treatment_ID;
        this->patient_ID = patient_ID;
        this->treatment_costs = treatment_costs;
        this->treatment_date.convert_date(treatment_date);
    }

    void set_treatment_ID(int treatment_ID) {
        this->treatment_ID = treatment_ID;
    }

    void read_treatment_date(void) {
        treatment_date.read_date();
    }

    void set_treatment_date(char _date[DATE_SIZE]) {
        treatment_date.convert_date(_date);
    }

    void set_patient_ID(int patient_ID) {
        this->patient_ID = patient_ID;
    }
    void set_treatment_costs(int treatment_costs) {
        this->treatment_costs = treatment_costs;
    }

    int get_treatment_ID(void) {
        return treatment_ID;
    }
    int get_patient_ID(void) {
        return patient_ID;
    }
    int get_treatment_costs(void) {
        return treatment_costs;
    }

};

class Outside_treatment : public Treatment {
private:
    int clinic_num;
    //class doctor;
public:
    Outside_treatment() {}
    Outside_treatment(int clinic_num, int treatment_ID, int patient_ID, int treatment_costs, char treatment_date[DATE_SIZE]) :Treatment(treatment_ID, patient_ID, treatment_costs, treatment_date) {
        this->clinic_num = clinic_num;
    }
    void set_clinic_num(int clinic_num) {
        this->clinic_num = clinic_num;
    }
    int get_clinic_num() {
        return this->clinic_num;
    }

    void print_outside_treatment(void) {
        cout << "The clinic num is " << clinic_num << "\n";
        cout << "The treatment ID is " << treatment_ID << "\n";
        cout << "The patient_ID is " << patient_ID << "\n";
        cout << "The treatment costs are " << treatment_costs << "\n";
        treatment_date.print_date();
        cout << " treatment date in compare format is " << treatment_date.get_compare();

    }

};

class Dynarray {
private:
    Treatment *pa;
    int length;
    int nextIndex;
public:
    Dynarray() {
        pa = new Treatment[10];
        length = 10;
        nextIndex = 0;
    }
    ~Dynarray() {
        delete[]pa;
    }
    void add(Treatment &add) {
        Treatment *pnewa;
        if (nextIndex == length) {
            length += 10;
            pnewa = new Treatment[length];
            for (int i = 0; i < nextIndex; ++i) {
                pnewa[i] = pa[i];
            }
            delete[]pa;
            pa = pnewa;
        }
        pa[nextIndex++] = add;
    }
    Treatment &operator[](int index) {
        return *(pa + index);
    }
};

int main(void) {
    Outside_treatment it;

    cout << "Enter the patient ID\n";
    int p_id;
    cin >> p_id;
    it.set_patient_ID(p_id);
    cin.ignore();
    cout << "set treatment date\n";
    it.read_treatment_date();

    cout << "enter costs\n";
    int costs;
    cin >> costs;
    it.set_treatment_costs(costs);

    cout << "enter section num\n";
    int sc_num;
    cin >> sc_num;
    it.set_clinic_num(sc_num);

    it.print_outside_treatment();

    Dynarray da;

    da.add(it);

    Treatment *yetanotherpointer = &da[0];


    int i = yetanotherpointer->get_patient_ID();
    cout << i << endl;

    while (1);
};

1 个答案:

答案 0 :(得分:1)

您正在创建一个Treatment个对象实例的数组。因此,您根本不能存储任何派生类型。如果您尝试将派生类型的对象分配给Treatment对象it will get sliced

你的预感是正确的。由于您正在处理多态类型,因此需要在数组中存储指向对象的指针,而不是实际的对象。然后,您可以将Treatment*指针存储到任何派生类型的对象,例如:

class Treatment {
    ...
public:
    ...

    // make the base class destructor virtual so calling
    // 'delete' on a base class pointer will invoke derived
    // destructors. Otherwise, if a derived class has any
    // data members with a non-trivial destructor, you will
    // cause leaking.  When writing polymorphic classes, it
    // is common practice to always define a virtual destructor,
    // just in case...
    //
    virtual ~Treatment() {} // <-- add this
    ..
};

class Dynarray {
private:
    Treatment **pa;
    int length;
    int capacity;

    // prevent copying the array, otherwise you risk
    // memory errors if multiple arrays own the same
    // objects being pointed at and try to free them
    // multiple times. Copying pointers to owned objects
    // is not safe, you need a cloning mechanism to
    // make deep-copies of derived types so a copied
    // array can point to its own objects...
    Dynarray(const Dynarray &) {}
    Dynarray& operator=(const Dynarray &) {}

public:
    Dynarray(int initialCapacity = 10) {
        pa = new Treatment*[initialCapacity];
        capacity = initialCapacity;
        length = 0;
    }

    ~Dynarray() {
        for (int i = 0; i < length; ++i)
            delete pa[i];
        delete[] pa;
    }

    void add(Treatment *add) {
        if (length == capacity) {
            Dynarray temp(capacity + 10);
            for (int i = 0; i < length; ++i) {
                temp.pa[i] = pa[i];
            }
            Treatment *ptr = temp.pa;
            temp.pa = pa;
            pa = ptr;
            capacity = temp.capacity;
        }

        pa[length++] = add;
    }

    Treatment* operator[](int index) {
        return pa[index];
    }
};

int main(void) {
    Outside_treatment *ot = new Outside_treatment;

    cout << "Enter the patient ID\n";
    int p_id;
    cin >> p_id;
    ot->set_patient_ID(p_id);
    cin.ignore();
    cout << "set treatment date\n";
    ot->read_treatment_date();

    cout << "enter costs\n";
    int costs;
    cin >> costs;
    ot->set_treatment_costs(costs);

    cout << "enter section num\n";
    int sc_num;
    cin >> sc_num;
    ot->set_clinic_num(sc_num);

    ot->print_outside_treatment();

    Dynarray da;
    da.add(ot);

    Treatment *t = da[0];

    int i = t->get_patient_ID();
    cout << i << endl;

    while (1);
};

另一方面,如果数组不需要拥有被指向的对象,只需存储指针,就可以删除析构函数中的delete循环,并且不需要调用者使用new创建存储的对象,并制作数组的副本是安全的,例如:

class Dynarray {
private:
    Treatment **pa;
    int length;
    int capacity;

public:
    Dynarray(int initialCapacity = 10) {
        pa = new Treatment*[initialCapacity];
        capacity = initialCapacity;
        length = 0;
    }

    // coping is OK since the objects being pointed
    // at are not owned by the array!
    Dynarray(const Dynarray &src) {
        pa = new Treatment*[src.capacity];
        capacity = src.capacity;
        length = src.length;
        for (int i = 0; i < length; ++i) {
            pa[i] = src.pa[i];
        }
    }

    Dynarray& operator=(const Dynarray &rhs) {
        if (&rhs != this) {
            Dynarray temp(rhs);
            Treatment **ptr = temp.pa;
            temp.pa = pa;
            pa = ptr;
            capacity = rhs.capacity;
            length = rhs.length;
        }
        return *this;
    }

    ~Dynarray() {
        delete[] pa;
    }

    void add(Treatment *add) {
        if (length == capacity) {
            Dynarray temp(capacity + 10);
            for (int i = 0; i < length; ++i) {
                temp.pa[i] = pa[i];
            }
            Treatment **ptr = temp.pa;
            temp.pa = pa;
            pa = ptr;
            capacity = temp.capacity;
        }

        pa[length++] = add;
    }

    Treatment* operator[](int index) {
        return pa[index];
    }
};

int main(void) {
    Outside_treatment ot;

    cout << "Enter the patient ID\n";
    int p_id;
    cin >> p_id;
    ot.set_patient_ID(p_id);
    cin.ignore();
    cout << "set treatment date\n";
    ot.read_treatment_date();

    cout << "enter costs\n";
    int costs;
    cin >> costs;
    ot.set_treatment_costs(costs);

    cout << "enter section num\n";
    int sc_num;
    cin >> sc_num;
    ot.set_clinic_num(sc_num);

    ot.print_outside_treatment();

    Dynarray da;
    da.add(&ot);

    Treatment *t = da[0];

    int i = t->get_patient_ID();
    cout << i << endl;

    while (1);
};