Return of non const handle to encapsulated data member

Метод возвращает указатель или ссылку на внутренний член объекта

Описание

Этот дефект происходит когда:

  • Метод класса возвращает указатель на элемент данных. Указатели включают указатели и ссылки.

  • Метод более доступен, чем элемент данных. Например, метод имеет спецификатор доступа public, но элементом данных является private или protected.

Риск

Спецификатор доступа определяет доступность члена класса. Например, член класса объявляется с private к спецификатору доступа нельзя получить доступ вне класса. Поэтому лицо, не являющееся членом какой-либо организации, недруг функции не могут изменить член.

Когда метод класса возвращает указатель на менее доступный элемент данных, изменения доступности члена. Например, если public метод возвращает указатель на private элемент данных, элементом данных является эффективно не private больше. Лицо, не являющееся членом какой-либо организации, недруг функциональный вызов public метод может использовать возвращенный указатель, чтобы просмотреть и изменить элемент данных.

Кроме того, если вы присваиваете указатель на элемент данных объекта к другому указателю, когда вы удаляете объект, второй указатель можно оставить, свиснув. Второй указатель указывает на часть объекта, который больше не существует.

Фиксация

Одна возможная фиксация должна постараться не возвращать указатель на элемент данных от метода класса. Возвратите элемент данных значением так, чтобы копия члена была возвращена. Изменение копии не изменяет элемент данных.

Если необходимо возвратить указатель, используйте const спецификатор с методом возвращает тип так, чтобы указатель позволил просматривать, но не изменять, элемент данных.

Примеры

развернуть все

#include <string>
#define NUM_RECORDS 100

struct Date {
    int dd;
    int mm;
    int yyyy;
};


struct Period {
    Date startDate;
    Date endDate;
};

class DataBaseEntry {
private:
    std::string employeeName;
    Period employmentPeriod;
public:
    Period* getPeriod(void);
};

Period* DataBaseEntry::getPeriod(void) {
    return &employmentPeriod;
}


void use(Period*);
void reset(Period*);

int main() {
    DataBaseEntry dataBase[NUM_RECORDS];
    Period* tempPeriod;
    for(int i=0;i < NUM_RECORDS;i++) {
        tempPeriod = dataBase[i].getPeriod();
        use(tempPeriod);
        reset(tempPeriod);
    }
    return 0;
}

void reset(Period* aPeriod) {
       aPeriod->startDate.dd = 1;
       aPeriod->startDate.mm = 1;
       aPeriod->startDate.yyyy = 2000;
}

В этом примере, employmentPeriod private к классу DataBaseEntry. Это поэтому неуязвимо для модификации лицом, не являющимся членом какой-либо организации, недругом функции. Однако возвращая указатель на employmentPeriod пропуски эта инкапсуляция. Например, лицо, не являющееся членом какой-либо организации, функционируют reset изменяет член startDate из employmentPeriod.

Коррекция: возвратите член значением

Одна возможная коррекция должна возвратить элемент данных employmentPeriod значением вместо указателя. Изменение возвращаемого значения не изменяет элемент данных, потому что возвращаемое значение является копией элемента данных.

#include <string>
#define NUM_RECORDS 100

struct Date {
    int dd;
    int mm;
    int yyyy;
};


struct Period {
    Date startDate;
    Date endDate;
};

class DataBaseEntry {
private:
    std::string employeeName;
    Period employmentPeriod;
public:
    Period getPeriod(void);
};

Period DataBaseEntry::getPeriod(void) {
    return employmentPeriod;
}


void use(Period*);
void reset(Period*);

int main() {
    DataBaseEntry dataBase[NUM_RECORDS];
    Period tempPeriodVal;
    Period* tempPeriod;
    for(int i=0;i < NUM_RECORDS;i++) {
        tempPeriodVal = dataBase[i].getPeriod();
        tempPeriod = &tempPeriodVal;
        use(tempPeriod);
        reset(tempPeriod);
    }
    return 0;
}

void reset(Period* aPeriod) {
       aPeriod->startDate.dd = 1;
       aPeriod->startDate.mm = 1;
       aPeriod->startDate.yyyy = 2000;
}

Информация о результате

Группа: Объектно-ориентированный
Язык: C++
Значение по умолчанию: Off
Синтаксис командной строки: BREAKING_DATA_ENCAPSULATION
Удар: носитель
ID CWE: 375, 767
Введенный в R2015b