С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
Bers
Заблокирован
1

Не хватает знаний. Не знаю, как на с++ реализовать возможность

15.11.2011, 10:31. Просмотров 2635. Ответов 67
Метки нет (Все метки)

Есть одна вещь, которую у меня сделать никак не получается.

В моей старенькой 2008 студии отсутствуют стандартизированные интеллектуальные указатели.
По этой причине я когда то написал собственные велосипеды для разных типов указателей.

Вот так выглядит прототип метода, который загружает данные в сильнвй указатель (который умеет шариться)


C++
1
2
3
4
void Input(TypeT* &Object); //принять право владения объектом. 
                                //Источник - указатель,
                                // который в конце операции обнулится 
                                //(больше не будет владеть объектом)
Обратите внимание, что на входе ссылка на указатель, а не просто указатель.
Это нужно специально для того, что бы можно было обнулить аргумент.

Вот так выглядит реализация метода:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void_TSharedPointer::Input(TypeT * &pObject)
{
    if(pObject==NULL_PTR) {   Release(); return;  }
 
    //следующее условие не корректно
    //Потому что , ситуация, 
    //когда аргумент указывает туда же,
    //куда и смартпоинтер возникнуть не может
    //Но покамест закроем на это глаза
 
    if(mp_Pointer != pObject)  
    {  
        Release();  
        mp_Pointer = pObject;
        mp_CounterLink=new int(1);
        pObject=NULL_PTR; 
    }
}
Обнуление аргумента гарантирует интеллектуальному указателю, что он действительно будит являться единственным владельцем объекта. И вызывающая сторона не сможет больше никак в обход его ничего сделать с ввереным ему объектом.

Все это здорово, и прекрасно.

Вот так это работает на практике:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
 
    int* ptr= new int;
 
    TSharedPointer<int> test(ptr);
    //теперь значение ptr равно NULL_PTR
    //объект принадлежит сильному указателю
    //а вызывающая сторона 
    //не имеет к нему прямого доступа
 
    EndProgramm();
}

Проблема в том, что я хочу сохранив инвариант сильного указателя, при этом иметь возможность написать вот так:
C++
1
2
3
4
5
6
7
int main()
{
    TSharedPointer<int> test(new int()  );  
    
  
    EndProgramm();
}
Компилятор мне на это пишет:

error C2664: TSharedPointer<TypeT>::TSharedPointer(TypeT *&): невозможно преобразовать параметр 1 из 'int *' в 'int *&'

Вопрос: как сохранить возможность обнуления входящих указателей, но при этом иметь возможность скармливать интеллектуальному указателю оператор new ?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.11.2011, 10:31
Ответы с готовыми решениями:

Реализовать двусвязный список. В разных узлах одного списка может быть любой объект одного из допустимых типов (своих знаний не хватает)
Вобщем делаю тестовые задания. На одно мне даже ответили, результат...

Не знаю как реализовать
Итак, пользователь может ввести, а может и ничего не вводить, но програма...

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

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

Не знаю как реализовать чтение из файла/запись в файл с особыми условиями
Добрый день! У меня есть файл file.txt с таким содержанием: xxx /x...

67
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 11:06 2
Bers, Как вариант просто перегрузить конструктор.
0
Bers
Заблокирован
15.11.2011, 11:13  [ТС] 3
Цитата Сообщение от ForEveR Посмотреть сообщение
Bers, Как вариант просто перегрузить конструктор.
Просто перегрузить не получится. Компилятор не сможет разобраться, какой метод вызвать - ссылкой, или без ссылки.
Будит что то вроде:

error C2668: TSharedPointer<TypeT>::Input: неоднозначный вызов перегруженной функции
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 11:31 4
м? не лучший прием.

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
#include <iostream>
#include <stdexcept>
 
template<class T>
class Pointer
{
public:
   Pointer(T*& obj)
   {
      object = obj;
   }
   Pointer(const T* obj)
   {
      object = const_cast<T*>(obj);
   }
   const T& operator *()
   {
      if (object)
      {
         return *object;
      }
      throw std::logic_error("Dereference of null pointer");
   }
private:
   T* object;
};
 
int main()
{
   Pointer<int> p1(new int());
   int* ptr = new int(1);
   Pointer<int> p2(ptr);
   std::cout << *p1 << std::endl;
   std::cout << *p2 << std::endl;
}
1
Bers
Заблокирован
15.11.2011, 11:40  [ТС] 5
ForEveR, я думал о таком варианте. Но меня смущает то, что приходится кастовать константность.

Алена в своём блоге пишет:
"Если снимать const с переменной, которая изначально была const, то дальнейшее её использование приведёт к undefined behaviour"(с)

http://alenacpp.blogspot.com/2005/08/c.html

Вот я и подумал.. тут беды никакой не будит? Я с этими константами до сих пор путаюсь
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 12:49 6
Bers, М. В данном случае она константа только как формальный параметр.
0
Bers
Заблокирован
15.11.2011, 12:57  [ТС] 7
Цитата Сообщение от ForEveR Посмотреть сообщение
Bers, М. В данном случае она константа только как формальный параметр.
Ну так то да. Номинально же объект не_константный, и номинальный указатель на него тоже не_константный, но почему тогда запускается именно метод с константным аргументом, а не метод с не_константной ссылкой?

Если передавать явный не_константный указатель, то он понимает, что нужно юзать метод с ссылкой, а не с константой.

Но если запихивать new construct(); запускается именно метод с константным указателем.

Как буд то бы оператор new возвращает константный указатель...

Ну и Алена спп тоже панику наводит)

в общем, я так и не совсем уловил принцип работы такого кода
0
silent_1991
Эксперт С++
5011 / 3071 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
Завершенные тесты: 1
15.11.2011, 13:44 8
Bers, а нужно ли всё это? ИМХО, шаред-птры обычно как раз создают так:
C++
1
shared_ptr< Type > shptr(new Type (...));
Если же программист разрешает ему владеть объектом, которым будет пользоваться также через нативные указатели, то такого программиста надо отшлёпать, и будет ему наука, когда он рантайм еррор получит. Или стояла цель написать именно такой указатель?
0
Bers
Заблокирован
15.11.2011, 14:04  [ТС] 9
Цитата Сообщение от silent_1991 Посмотреть сообщение
Если же программист разрешает ему владеть объектом, которым будет пользоваться также через нативные указатели, то такого программиста надо отшлёпать, и будет ему наука, когда он рантайм еррор получит. Или стояла цель написать именно такой указатель?
Задача - получить класс сильного указателя, который обеспечивает безопасность собственной работы.

Для этого, если ему скормят обычный указатель, он должен суметь его обнулить
Сильный указатель не будит шлёпать нерадивого программиста по попе, и не будит дожидаться рантайм еррор.

Сильный указатель просто не позволит вызывающей стороне его поломать.
0
silent_1991
Эксперт С++
5011 / 3071 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
Завершенные тесты: 1
15.11.2011, 14:19 10
Bers, однако сам может поломать вызывающую сторону, да?))
0
Bers
Заблокирован
15.11.2011, 14:23  [ТС] 11
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, однако сам может поломать вызывающую сторону, да?))
Вариант который предложил ForEveR реально работает. Я никаких проблем не вижу.

Если реально тут нет мины замедленного действия - то это отличный вариант. То, что нужно.

Тогда класс вполне себе надежный получится. Придется ещё пораскинуть мозгами, как сделать так, что б его суметь поломать

Но вдруг там что-то не так. Я даже не до конца понимаю почему если закинуть new , то сработает константный метод.
0
silent_1991
Эксперт С++
5011 / 3071 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
Завершенные тесты: 1
15.11.2011, 14:33 12
Цитата Сообщение от Bers Посмотреть сообщение
Я никаких проблем не вижу.
Я о том, что на вызывающей стороне указатель становится невалидным. С моей точки зрения, это очень даже нехорошо.

Цитата Сообщение от Bers Посмотреть сообщение
Я даже не до конца понимаю почему если закинуть new , то сработает константный метод.
Потому что отбрасывание константности - первый шаг компилятора при поиске кандидатов перегруженной функции/метода, если полного совпадения не нашлось. Поскольку оно нашлось, этого первого шага не происходит. Если я не ошибаюсь, конечно.

Добавлено через 3 минуты
Нет, похоже, всё-таки ошибаюсь...
0
Bers
Заблокирован
15.11.2011, 14:35  [ТС] 13
Цитата Сообщение от silent_1991 Посмотреть сообщение
Я о том, что на вызывающей стороне указатель становится невалидным. С моей точки зрения, это очень даже нехорошо.
Если класс забирает себе право владения объектом, то на вызывающей стороне в принципе не может оставаться валидного указателя.

Иначе какой смысл вообще юзать сильные указатели?

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

Я себе даже представить не могу ситуацию, зачем может понадобится сильный указатель, если при этом нужно что бы оригинал остался валидным.
0
silent_1991
Эксперт С++
5011 / 3071 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
Завершенные тесты: 1
15.11.2011, 15:05 14
Цитата Сообщение от Bers Посмотреть сообщение
Я себе даже представить не могу ситуацию, зачем может понадобится сильный указатель, если при этом нужно что бы оригинал остался валидным.
Так вот поэтому такие указатели и создают без промежуточных сырых указателей, а выделяя память прямо в аргументе конструктора.
0
Bers
Заблокирован
15.11.2011, 15:07  [ТС] 15
Цитата Сообщение от silent_1991 Посмотреть сообщение
Так вот поэтому такие указатели и создают без промежуточных сырых указателей, а выделяя память прямо в аргументе конструктора.
что произойдёт с бустовским указателем, если я скормлю ему обычный указатель?
Он его не обнулит? То есть бустовский указатель не инвариантен?
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 15:15 16
Bers, Не обнулит.

C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <boost/shared_ptr.hpp>
 
int main()
{
   int* pointer = new int(5);
   boost::shared_ptr<int> ptr(pointer);
   std::cout << *pointer << std::endl;
}
Добавлено через 34 секунды
http://liveworkspace.org/code/9002825d3c3cffc992ec59bc80aebaf2

И ни один smart_pointer таким не занимается. Это не логично.
0
Bers
Заблокирован
15.11.2011, 15:17  [ТС] 17
Цитата Сообщение от ForEveR Посмотреть сообщение
Это не логично.
В умной книжке читал: инструмент должно быть легко использовать правильно. И затрудненно неправильно.

почему не логично?
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 15:20 18
Bers, Да потому что. Человек создал указатель. Подал его в smart_pointer. А потом захотел использовать так, без вызова get() и получил бабах. Не красиво.
Ну и плюс к тому бустовские смарты могут использоваться далеко не только с new.
0
Bers
Заблокирован
15.11.2011, 15:20  [ТС] 19
Цитата Сообщение от ForEveR Посмотреть сообщение
И ни один smart_pointer таким не занимается. Это не логично.

Кстати, идею обнулять оригинал при изъятии у него права владения, я подглядел у стд::ауто_птр
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.11.2011, 15:21 20
Bers, std::auto_ptr не присутствует в новом стандарте. Вместо него shared/weak/scoped etc.
0
15.11.2011, 15:21
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2011, 15:21

Игра в кости: реализовать мини-казино; реализовать возможность игры 2 человек между собой
Уважаемые форумчане! Подскажите, пож-та, где можно посмотреть программу игры...

Числа считаются равными если они отличаются не более, чем на (10^-12) / c++ / как реализовать эту возможность?
На плоскости заданы три точки А, В и С. Определить, какая из двух последних...

Выручайте, знаний не хватает
Доброго всем дня. Пытался решить практическую задачу. Заключается она в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru