Return of non const handle to encapsulated data member

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

Описание

Этот дефект возникает, когда:

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

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

Риск

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

Когда метод класса возвращает указатель на менее доступный представитель данных, изменяется доступность представителя. Для образца, если a public метод возвращает указатель на private представитель данных, представитель данных эффективно не private больше. Функция non member, non friend, вызывающая 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
Влияние: Средний
ИДЕНТИФИКАТОР CWE : 375, 767
Введенный в R2015b