Форум программистов, компьютерный форум CyberForum.ru

Обход инкапсуляции класса - C++

Восстановить пароль Регистрация
 
laucher
0 / 0 / 0
Регистрация: 31.10.2013
Сообщений: 20
02.11.2013, 13:12     Обход инкапсуляции класса #1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
 
using namespace std;
 
class My_class {
private:
    char* name;
public:
    My_class() {
        
            name = new char[100];
            cin>>name;
 
    }
    ~My_class() {
        if (name) {
            delete[] name;
        }
    }
    
    const char * getname() {
        return name;
    }
    void show() {
        cout<<name;
    }
};
 
int main() {
    My_class my;
    const char *    k = my.getname();
    char* n = (char* ) k; //  Здесь происходит смена типа с конст на не конст?
    *n = '1';//
    my.show();
    system("pause");
    return 0;
}
Консты я расставлял, так как думал, что это поможет защитить поле класса извне. Как видите, в мейне его изменить получается

Вопрос, как составить здесь грамотную защиту поля извне. Я думал о том, чтобы создавать локальную переменную в функции getname и возвращать её:
C++
1
2
3
4
5
    char * getname() {
        char * temp = new char[strlen(name) +1 ];
        strcpy(temp,name);
        return temp;
    }
Вопрос 1 : Не будет ли здесь утечек памяти? Ведь я выделяю память с помощью new, но у меня нет delete. Или она самоуничтожается при достижении конца функции?
Вопрос 2:
C++
1
2
3
const char *    k = my.getname();
    char* n = (char* ) k; //  Здесь происходит смена типа с конст на не конст?
    *n = '1';//
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
lemegeton
 Аватар для lemegeton
2910 / 1339 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
02.11.2013, 13:24     Обход инкапсуляции класса #2
Больше констов, хороших и разных.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <cstring>
 
class Person {
 public:
  Person(const char *name) 
    : name(strcpy(new char[strlen(name) + 1], name)) {}
  // первый конст означает константный указатель,
  // второй конст -- константное значение указателя
  const char * const getName() {
    return name;
  }
 private:
  char *name;
};
 
int main(int, char**) {
  Person john("john");
 
  // Так не выйдет
  //const char *name = john.getName();
  std::cout << john.getName() << std::endl;
  
  return 0;
}
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.11.2013, 13:31     Обход инкапсуляции класса #3
Цитата Сообщение от laucher Посмотреть сообщение
Не будет ли здесь утечек памяти?
Если на new нет соответствующего delete, то утечки будут.
Цитата Сообщение от laucher Посмотреть сообщение
char* n = (char* ) k; // Здесь происходит смена типа с конст на не конст?
Происходит. Приведения в Си-стиле лучше заменить соответствующим _cast'ом
ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,057
02.11.2013, 13:37     Обход инкапсуляции класса #4
Цитата Сообщение от laucher Посмотреть сообщение
Вопрос 1 : Не будет ли здесь утечек памяти? Ведь я выделяю память с помощью new, но у меня нет delete. Или она самоуничтожается при достижении конца функции?
будет
самоуничтожится указатель на эту память, а память останется
и в другом случае это привело бы к утечке, выделенная память есть а кто указывает на неё нету, значит достучатся не можем
но у тебя этот указатель отдается наружу
Цитата Сообщение от laucher Посмотреть сообщение
return temp;
значит пускай удаляет тот кому мы передали этот указатель
Но при таком подходе нарушается правило "кто выделил тот и удаляет",что может привести к трудноуловимым ошибкам
scenotaph
120 / 120 / 15
Регистрация: 29.03.2013
Сообщений: 237
02.11.2013, 13:47     Обход инкапсуляции класса #5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <cstring>
 
class Person {
 public:
  Person(const char *name) 
    : name(strcpy(new char[strlen(name) + 1], name)) {}
  // первый конст означает константный указатель,
  // второй конст -- константное значение указателя
  const char * const getName() {
    return name;
  }
 private:
  char *name;
};
 
int main(int, char**) {
  Person john("john");
 
 
  const char *name = john.getName();
  char * n = (char*) name;
  *n = '1';
  std::cout << john.getName() << std::endl;
  
  return 0;
}
Вывод: 1ohn

OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
02.11.2013, 13:55     Обход инкапсуляции класса #6
Цитата Сообщение от laucher Посмотреть сообщение
C++
1
    char*
утечки
std::string
lemegeton
 Аватар для lemegeton
2910 / 1339 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
02.11.2013, 14:02     Обход инкапсуляции класса #7
Пардон, чет я попутался.

Снятие constant value модификатора (приведение к не-консту) ведет к UB -- компилятор сделает так, как захочет. В вашем случае, он хочет допустить такое поведение.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.11.2013, 16:04     Обход инкапсуляции класса #8
Цитата Сообщение от lemegeton Посмотреть сообщение
Снятие constant value модификатора (приведение к не-консту) ведет к UB
Тут, я думаю, возможны исключения:
1. Если запись не производить, а только снять const, то проблем быть не должно.
2. Если изначальное значение не константа:
C++
1
2
3
    int i = 42;
    const int* c = &i;
    *const_cast<int*>(c) = 100500;
, то тоже всё ОК.
laucher
0 / 0 / 0
Регистрация: 31.10.2013
Сообщений: 20
02.11.2013, 16:57  [ТС]     Обход инкапсуляции класса #9
OhMyGodSoLong, Нужно именно char*
Спасибо отписавшимся
ап. Вопрос с грамотной инкапсуляцией остался
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.11.2013, 17:00     Обход инкапсуляции класса #10
laucher, С++ не тот язык, где нельзя насрать в класс, если этого действительно очень хочется. Имеет смысл делать защиту только от случайного изменения данных. Другой защиты быть не может.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
02.11.2013, 18:33     Обход инкапсуляции класса #11
Цитата Сообщение от laucher Посмотреть сообщение
Вопрос с грамотной инкапсуляцией остался
Pimpl.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Person.h
struct PersonData;
 
class Person
{
public:
    Person(const char *name);
 
    const char* getName() const;
 
    // и весь остальной интерфейс
 
private:
    std::unique_ptr<PersonData> m_m;
};
 
 
// Person.cpp
#include "Person.h"
 
struct PersonData
{
    const char *name;
 
    PersonData(const char *name)
      : name(NULL)
    {
        this->name = strdup(name);
    }
    
    ~PersonData()
    {
        free(name);
    }
};
 
Person::Person(const char *name)
  : m_m(new PersonData(name))
{}
 
const char* Person::getName() const
{
    return m_m->name;
}
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
02.11.2013, 20:06     Обход инкапсуляции класса #12
Цитата Сообщение от lemegeton Посмотреть сообщение
C++
1
//const char *name = john.getName();
А зачем это запрещать?

OhMyGodSoLong, а зачем PersonData торчит наружу и почему можно не писать деструктор Person?
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.11.2013, 20:39     Обход инкапсуляции класса #13
Цитата Сообщение от ct0r Посмотреть сообщение
почему можно не писать деструктор Person?
а зачем он нужен? Удалением PersonData заведует std::unique_ptr.
Цитата Сообщение от ct0r Посмотреть сообщение
а зачем PersonData торчит наружу
В каком смысле?
Dmitriy_M
1295 / 1176 / 105
Регистрация: 20.03.2009
Сообщений: 4,211
Записей в блоге: 11
02.11.2013, 20:53     Обход инкапсуляции класса #14
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Pimpl.
Тут он не поможет.
Цитата Сообщение от laucher Посмотреть сообщение
Вопрос с грамотной инкапсуляцией остался
Возвращать не указатель или ссылку, а объект.
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
02.11.2013, 21:11     Обход инкапсуляции класса #15
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Tulosba Посмотреть сообщение
В каком смысле?
Ну в смысле зачем делать имя PersonData видимым извне, если можно обойтись PersonData как вложенным классом?

Цитата Сообщение от Tulosba Посмотреть сообщение
а зачем он нужен? Удалением PersonData заведует std::unique_ptr.
unique_ptr для удаления объекта через delete нужен полный тип. Поэтому по идее нам нужно явно написать деструктор в файле реализации, иначе компилятор не сможет сгенерить деструктор из места, где PersonData не определена.

Добавлено через 9 минут
laucher, все нормально с инкапсуляцией. Зачем мешать другому разработчику, если он явно дополнительными телодвижениями указывает, что он знает, что и зачем делает?
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Возвращать не указатель или ссылку, а объект.
Это того не стоит.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
02.11.2013, 21:12     Обход инкапсуляции класса #16
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Тут он не поможет.
Ок.
C++
1
2
3
4
const char* Person::getName() const
{
    return strdup(m_m->name);
}
Цитата Сообщение от ct0r Посмотреть сообщение
Ну в смысле зачем делать имя PersonData видимым извне, если можно обойтись PersonData как вложенным классом?
Затем, что 1) это иллюстративный пример, 2) PersonData короче Person::Data, 3) так сделано в Qt

Цитата Сообщение от ct0r Посмотреть сообщение
unique_ptr для удаления объекта через delete нужен полный тип. Поэтому по идее нам нужно явно написать деструктор в файле реализации, иначе компилятор не сможет сгенерить деструктор из места, где PersonData не определена.
Больше не буду писать код не думая, спасибо.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.11.2013, 22:39     Обход инкапсуляции класса #17
Цитата Сообщение от ct0r Посмотреть сообщение
unique_ptr для удаления объекта через delete нужен полный тип. Поэтому по идее нам нужно явно написать деструктор в файле реализации, иначе компилятор не сможет сгенерить деструктор из места, где PersonData не определена.
Да, интересно получается. Явный пустой деструктор лучше чем неявный.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.11.2013, 23:35     Обход инкапсуляции класса
Еще ссылки по теме:

C++ Об инкапсуляции данных в ООП
Разница между понятиями "Обход в прямом направлении" и "Итерационный прямой обход" C++
Как получить доступ к методам класса, который содержится в векторе класса C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6172 / 2901 / 284
Регистрация: 04.12.2011
Сообщений: 7,722
Записей в блоге: 3
02.11.2013, 23:35     Обход инкапсуляции класса #18
Мне самому очень интересно как бы здесь лучше поступить. С одной стороны поле - си-строка и значит если вернуть указатель, то защитить никак не получится. У OhMyGodSoLong интересная мысль мелькнула. Что если действительно возвращать копию другого типа. Например string:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include<string>
#include <windows.h>
using namespace std;
class A{
public:
A(char *nam);
~A();
string get_name();
private:
char *name;
};
A::A(char *nam){
name = new char[strlen(nam)+1];
strcpy(name, nam);
}
A::~A(){
delete []name;
}
string 
A::
get_name(){
return name;
}
int main()
{
SetConsoleCP (1251); SetConsoleOutputCP (1251);
A a("Au!");
cout<<a.get_name();
cout << endl;
system ("pause" );
    return 0;
}
Хотя, может я просто вообще не понял о чем речь.
Yandex
Объявления
02.11.2013, 23:35     Обход инкапсуляции класса
Ответ Создать тему
Опции темы

Текущее время: 05:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru