Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 31.10.2013
Сообщений: 20
1

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

02.11.2013, 13:12. Показов 1651. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
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';//
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.11.2013, 13:12
Ответы с готовыми решениями:

Обход членов класса
Вопрос: Возможно ли на С++ вообще написать шаблон, который будет генерировать функцию,...

Обход полей класса
Здравствуйте уважаемые форумчане, подскажите как решить такую ситуацию наиболее верным способом......

Рекурсивный обход. Не могу сделать табуляцию. Обход с выводом имен файлов
Задание простое, ну по крайней мере на первый взгляд. Написать скрипт обхода вложенных директорий с...

Попытка Инкапсуляции
Почему при попытке описать метод класса за его пределами, компилятор выдает ошибку? class A {...

17
4772 / 2581 / 893
Регистрация: 29.11.2010
Сообщений: 5,582
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;
}
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.11.2013, 13:31 3
Цитата Сообщение от laucher Посмотреть сообщение
Не будет ли здесь утечек памяти?
Если на new нет соответствующего delete, то утечки будут.
Цитата Сообщение от laucher Посмотреть сообщение
char* n = (char* ) k; // Здесь происходит смена типа с конст на не конст?
Происходит. Приведения в Си-стиле лучше заменить соответствующим _cast'ом
1
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,520
02.11.2013, 13:37 4
Цитата Сообщение от laucher Посмотреть сообщение
Вопрос 1 : Не будет ли здесь утечек памяти? Ведь я выделяю память с помощью new, но у меня нет delete. Или она самоуничтожается при достижении конца функции?
будет
самоуничтожится указатель на эту память, а память останется
и в другом случае это привело бы к утечке, выделенная память есть а кто указывает на неё нету, значит достучатся не можем
но у тебя этот указатель отдается наружу
Цитата Сообщение от laucher Посмотреть сообщение
return temp;
значит пускай удаляет тот кому мы передали этот указатель
Но при таком подходе нарушается правило "кто выделил тот и удаляет",что может привести к трудноуловимым ошибкам
1
120 / 120 / 47
Регистрация: 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

1
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
02.11.2013, 13:55 6
Цитата Сообщение от laucher Посмотреть сообщение
C++
1
    char*
утечки
std::string
1
4772 / 2581 / 893
Регистрация: 29.11.2010
Сообщений: 5,582
02.11.2013, 14:02 7
Пардон, чет я попутался.

Снятие constant value модификатора (приведение к не-консту) ведет к UB -- компилятор сделает так, как захочет. В вашем случае, он хочет допустить такое поведение.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
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;
, то тоже всё ОК.
0
0 / 0 / 0
Регистрация: 31.10.2013
Сообщений: 20
02.11.2013, 16:57  [ТС] 9
OhMyGodSoLong, Нужно именно char*
Спасибо отписавшимся
ап. Вопрос с грамотной инкапсуляцией остался
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.11.2013, 17:00 10
laucher, С++ не тот язык, где нельзя насрать в класс, если этого действительно очень хочется. Имеет смысл делать защиту только от случайного изменения данных. Другой защиты быть не может.
0
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 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;
}
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
02.11.2013, 20:06 12
Цитата Сообщение от lemegeton Посмотреть сообщение
C++
1
//const char *name = john.getName();
А зачем это запрещать?

OhMyGodSoLong, а зачем PersonData торчит наружу и почему можно не писать деструктор Person?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.11.2013, 20:39 13
Цитата Сообщение от ct0r Посмотреть сообщение
почему можно не писать деструктор Person?
а зачем он нужен? Удалением PersonData заведует std::unique_ptr.
Цитата Сообщение от ct0r Посмотреть сообщение
а зачем PersonData торчит наружу
В каком смысле?
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
02.11.2013, 20:53 14
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Pimpl.
Тут он не поможет.
Цитата Сообщение от laucher Посмотреть сообщение
Вопрос с грамотной инкапсуляцией остался
Возвращать не указатель или ссылку, а объект.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
02.11.2013, 21:11 15
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Tulosba Посмотреть сообщение
В каком смысле?
Ну в смысле зачем делать имя PersonData видимым извне, если можно обойтись PersonData как вложенным классом?

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

Добавлено через 9 минут
laucher, все нормально с инкапсуляцией. Зачем мешать другому разработчику, если он явно дополнительными телодвижениями указывает, что он знает, что и зачем делает?
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Возвращать не указатель или ссылку, а объект.
Это того не стоит.
1
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 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 не определена.
Больше не буду писать код не думая, спасибо.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.11.2013, 22:39 17
Цитата Сообщение от ct0r Посмотреть сообщение
unique_ptr для удаления объекта через delete нужен полный тип. Поэтому по идее нам нужно явно написать деструктор в файле реализации, иначе компилятор не сможет сгенерить деструктор из места, где PersonData не определена.
Да, интересно получается. Явный пустой деструктор лучше чем неявный.
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
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;
}
Хотя, может я просто вообще не понял о чем речь.
0
02.11.2013, 23:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.11.2013, 23:35
Помогаю со студенческими работами здесь

Закоментированный пример инкапсуляции
Приведите пожалуйста пример инкапсуляции в ООП на php.Желательно, с комментариями, чтобы я понял)

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

Изучение инкапсуляции и абстракции
Всем доброго вечера у меня очередная лабораторка. Завдання. Створити на мові Java клас, який...

Нарушение инкапсуляции метода
Уважаемые, опытные, подскажите, чем может грозить нарушение инкапсуляции метода класса, кроме того...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru