Неверный вывод для массива класса - PullRequest
0 голосов
/ 14 марта 2020

Итак, мне были предоставлены следующие классы вместе с переменными и методами-членами (включая конструкторы. Никаких дополнительных переменных и методов не следует добавлять). Я написал следующие коды для предоставленных методов:

Класс контейнера

# define INTEGER 1
# define INT_ARRAY 2
# define INT_MATRIX 3

class Container{
int *value;
int *valueArray;
int **valueMatrix;
int firstDim, secondDim;    
int storedType;

void reset(){
    if (value != NULL){
        delete value;
        value=NULL;
    }
    if (valueArray != NULL){
        delete[] valueArray;
        valueArray=NULL;
    }
    if (valueMatrix != NULL){
        for(int i=0;i<firstDim;i++){
            delete[] valueMatrix[i];
        }
        delete[] valueMatrix;
        valueMatrix=NULL;
    }
    firstDim = 0;
    secondDim = 0;
    storedType = -1;
}

public:
Container(){
    cout << "Constructing Container with empty parameter" << endl;
    cout << "___________________________________________" << endl;
    value = NULL;
    valueArray = NULL;
    valueMatrix = NULL;
    firstDim = 0;
    secondDim = 0;
    storedType = -1;
}

Container (int val){
    cout << "Constructing Container with a single integer parameter" << endl;
    cout << "______________________________________________________" << endl;
    value=new int(val);
    valueArray = NULL;
    valueMatrix = NULL;
    firstDim = 0;
    secondDim = 0;
    storedType = INTEGER;
}

Container (int *valArr, int len){
    cout << "Constructing Container with integer array parameter" << endl;
    cout << "___________________________________________________" << endl;
    valueArray=new int[len];
    value=NULL;
    valueMatrix=NULL;
    for(int i=0;i<len;i++) valueArray[i]=valArr[i];
    firstDim = len;
    secondDim = 0;
    storedType = INT_ARRAY;
}

Container (int **valMat, int r, int c){
    cout << "Constructing Container with integer matrix parameter" << endl;
    cout << "____________________________________________________" << endl;
    valueMatrix=new int*[r];
    value=NULL;
    valueArray=NULL;
    for(int i=0;i<r;i++){
        valueMatrix[i]=new int[c];
        for(int j=0;j<c;j++){
            valueMatrix[i][j]=valMat[i][j];
        }
    }
    firstDim=r;
    secondDim=c;
    storedType=INT_MATRIX;
}

Container(const Container &obj){
    cout << "Calling copy constructor of Container" << endl;
    cout << "_____________________________________" << endl;

    firstDim=obj.firstDim;
    secondDim=obj.secondDim;
    storedType=obj.storedType;
    value=new int;
    value=obj.value;
    valueArray=new int[firstDim];
    valueArray=obj.valueArray;
    valueMatrix=new int*[firstDim];
    for(int k=0;k<obj.firstDim;k++){
        valueMatrix[k]=new int[secondDim];
    }
    valueMatrix=obj.valueMatrix;
}


void setItem (int val){
    reset();
    value=new int(val);
    firstDim = 0;
    secondDim = 0;
    storedType = INTEGER;
    valueArray=NULL;
    valueMatrix=NULL;
}

 void setItem(int *valArr, int len){
    reset();
    valueArray=new int[len];
    for(int i=0;i<len;i++) valueArray[i]=valArr[i];
    firstDim = len;
    secondDim = 0;
    storedType = INT_ARRAY;
    value=NULL;
    valueMatrix=NULL;
}

 void setItem(int **valMat, int r, int c){
    reset();
    valueMatrix=new int*[r];
    for(int i=0;i<r;i++){
        valueMatrix[i]=new int[c];
        for(int j=0;j<c;j++){
            valueMatrix[i][j]=valMat[i][j];
        }
    }
    firstDim=r;
    secondDim=c;
    storedType=INT_MATRIX;
    value=NULL;
    valueArray=NULL;
}

void * getItem(){
    if (value != NULL) return value;
    if (valueArray != NULL) return valueArray;
    if (valueMatrix != NULL) return valueMatrix;
    return NULL;
}

int getFirstDim(){
    return firstDim;
}

int getSecondDim(){
    return secondDim;
}

int getStoredType(){
    return storedType;
}

void print(){
    if (value != NULL){
        cout << "There is only an integer value in the container object" << endl;
        cout << "The value is: " << *value << endl;
    }
    else if (valueArray != NULL){
        cout << "There is an integer array in the container object" << endl;
        cout << "The values stored in the array are:" << endl;
        for (int i=0; i<firstDim; i++){
            cout << valueArray[i] << " ";
        }
        cout << endl;
    }
    else if (valueMatrix != NULL){
        cout << "There is an integer matrix in the container object" << endl;
        cout << "The values stored in the matrix are:" << endl;
        for (int i=0; i<firstDim; i++){
            for (int j=0; j<secondDim; j++){
                cout << valueMatrix[i][j] << " ";
            }
            cout << endl;
        }
    }
    else{
        cout << "The object has no elements" << endl;
    }
}

~Container(){
    if (value != NULL){
        cout << "Freeing allocated memory for a single integer" << endl;
        delete value;
        value = NULL;
    }
    if (valueArray != NULL){
        cout << "Freeing allocated memory for integer array" << endl;
        delete[] valueArray;
        valueArray = NULL;
    }
    if (valueMatrix != NULL){
        cout << "Freeing allocated memory for integer matrix" << endl;
        for(int i=0;i<firstDim;i++){
            delete[] valueMatrix[i];
        }
        delete[] valueMatrix;
        valueMatrix = NULL;
    }
    firstDim = 0;
    secondDim = 0;
    storedType = -1;
    cout << "_____________________" << endl;
    cout << "Destructing Container" << endl;
 }
};

Класс ContainerArray

class ContainerArray{
Container *arrayOfContainers;
int allocatedSize;
public:
ContainerArray(){
    allocatedSize = 0;
    arrayOfContainers = NULL;
}

ContainerArray(int size){
    allocatedSize=size;
    arrayOfContainers=new Container[size];
}

void setAllocatedSize(int sz){
    if(allocatedSize){
        delete[] arrayOfContainers;
    }
    allocatedSize=sz;
    arrayOfContainers=new Container[sz];
}

int getAllocatedSize(){
    return allocatedSize;
}

Container getItemAt(int index){
    if (index >= allocatedSize){
        cout << "Cannot get item, Exception: Container Array index out of bound";
        exit(0);
    }
    return arrayOfContainers[index];
}

void setItemAt(Container p,int x){
    if(x >= allocatedSize) cout << "Exception: Container Array index out of bound";
    else{
        if(p.getStoredType() == 1) arrayOfContainers[x].setItem(*(int*)p.getItem());
        else if(p.getStoredType() == 2) arrayOfContainers[x].setItem((int*)p.getItem(),p.getFirstDim());
        else if(p.getStoredType() == 3) arrayOfContainers[x].setItem((int**)p.getItem(),p.getFirstDim(),p.getSecondDim());
    }
}

~ContainerArray(){
    delete[] arrayOfContainers;
    allocatedSize=0;
    arrayOfContainers=NULL;
  }
};

функция main ()

int main()
{

Контейнер a; Контейнер b (100);

int *arr = new int[3];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;

Container c(arr, 3);

int **mat = new int*[2];
mat[0] = new int[3];
mat[0][0] = 1;
mat[0][1] = 2;
mat[0][2] = 3;
mat[1] = new int[3];
mat[1][0] = 4;
mat[1][1] = 5;
mat[1][2] = 6;

Container d(mat, 2, 3);
    int firstObjArraySize = 3, secondObjArraySize = 4;
ContainerArray containerArray1;
ContainerArray containerArray2(secondObjArraySize);
cout << secondObjArraySize << " constructors with empty parameters are called" << endl;

containerArray1.setAllocatedSize(firstObjArraySize);
cout << firstObjArraySize << " constructors with empty parameters are called" << endl;

containerArray1.setItemAt(a, 0);
containerArray1.setItemAt(b, 2);
containerArray1.setItemAt(c, 1);

containerArray2.setItemAt(c, 0);
containerArray2.setItemAt(d, 1);

for (int i=0; i<3; i++){
    cout << i << "-th element of 1st container array:" << endl;
    containerArray1.getItemAt(i).print();
}

for (int i=0; i<2; i++){
    cout << i << "-th element of 2nd container array:" << endl;
    containerArray2.getItemAt(i).print();
}

return 0;
}

Проблема:

Объект containerArray1 хорошо печатается. Но массив, инициализированный в функции main (), снова используется в объекте containeraArray2 . Из-за деструктора, освобождающего память предыдущего объекта, содержимое массива не распечатывается как требуется. Но остальное содержимое печатается по желанию. Я знаю, что могла быть какая-то проблема в выделении моей памяти Dynami c. Но я не могу понять. Буду признателен за любую помощь.

Спасибо ...

ОЖИДАЕМЫЙ ВЫХОД

Выход для объекта containerArray1 :

0-th element of 1st container array:
Calling copy constructor of Container
_____________________________________
The object has no elements
_____________________
Destructing Container
1-th element of 1st container array:
Calling copy constructor of Container
_____________________________________
There is an integer array in the container object
The values stored in the array are:
10 20 30 
Freeing allocated memory for integer array
_____________________
Destructing Container
2-th element of 1st container array:
Calling copy constructor of Container
_____________________________________
There is only an integer value in the container object
The value is: 100
Freeing allocated memory for a single integer
_____________________
Destructing Container

Вывод для containerArray2 объект:

0-th element of 2nd container array:
Calling copy constructor of Container
_____________________________________
There is an integer array in the container object
The values stored in the array are:
10 20 30 
Freeing allocated memory for integer array
_____________________
Destructing Container
1-th element of 2nd container array:
Calling copy constructor of Container
_____________________________________
There is an integer matrix in the container object
The values stored in the matrix are:
1 2 3 
4 5 6 
Freeing allocated memory for integer matrix
_____________________
Destructing Container

Проблема заключается в 0-м элементе 2-го объекта-контейнера. Массив печатает резкие числа.

1 Ответ

1 голос
/ 14 марта 2020

Ваш конструктор копирования не копирует значения, а просто сгибает указатели.

Вы выделили память, но затем перезаписали указатель на выделенную память.

Так что вместо этого

value=new int;
value=obj.value;
valueArray=new int[firstDim];
valueArray=obj.valueArray;
valueMatrix=new int*[firstDim];
for(int k=0;k<obj.firstDim;k++){
    valueMatrix[k]=new int[secondDim];
}
valueMatrix=obj.valueMatrix;

Вам нужно сделать что-то вроде этого:

    value = nullptr;
    valueArray = nullptr;
    valueMatrix = nullptr;
    storedType = obj.storedType;
    switch (storedType)
    {
    case INTEGER:
        value = new int;
        *value = *(obj.value);
        break;
    case INT_ARRAY:
        valueArray = new int[firstDim];
        std::copy(obj.valueArray, obj.valueArray + firstDim, valueArray);
        break;
    case INT_MATRIX:
        valueMatrix = new int* [firstDim];
        for (int k = 0; k < obj.firstDim; k++) {
            valueMatrix[k] = new int[secondDim];
            std::copy(obj.valueMatrix[k], obj.valueMatrix[k] + secondDim, valueMatrix[k]);
        }
        break;
    }

Поскольку вы просто имеете дело со значениями типа int, вы можете просто использовать memcpy вместо std::copy, но я просто подумал, что упомяну общий случай.

...