Возвратитесь из не указатель const на инкапсулированный элемент данных

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

Описание

Возвратитесь из указателя неconst на инкапсулированный элемент данных, происходит когда:

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

  • Метод более доступен, чем элемент данных. Например, метод имеет спецификатор доступа 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