Заблокирован
1

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

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

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

В моей старенькой 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.11.2011, 10:31
Ответы с готовыми решениями:

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

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

Не хватает знаний. Выбор между ноутом и стационар
Здравствуйте, друзья. В общем хочу себе купить компьютер. Бюджет около 420 у.е. (плюс минус - но...

Не могу сделать три задания, не хватает ещё знаний языка
Задание 1. Найти страну с наибольшим производством стали Задание 2. Найти страны, добыч нефти в...

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

error C2668: TSharedPointer<TypeT>::Input: неоднозначный вызов перегруженной функции
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
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
Заблокирован
15.11.2011, 11:40  [ТС] 5
ForEveR, я думал о таком варианте. Но меня смущает то, что приходится кастовать константность.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Я себе даже представить не могу ситуацию, зачем может понадобится сильный указатель, если при этом нужно что бы оригинал остался валидным.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
15.11.2011, 15:05 14
Цитата Сообщение от Bers Посмотреть сообщение
Я себе даже представить не могу ситуацию, зачем может понадобится сильный указатель, если при этом нужно что бы оригинал остался валидным.
Так вот поэтому такие указатели и создают без промежуточных сырых указателей, а выделяя память прямо в аргументе конструктора.
0
Заблокирован
15.11.2011, 15:07  [ТС] 15
Цитата Сообщение от silent_1991 Посмотреть сообщение
Так вот поэтому такие указатели и создают без промежуточных сырых указателей, а выделяя память прямо в аргументе конструктора.
что произойдёт с бустовским указателем, если я скормлю ему обычный указатель?
Он его не обнулит? То есть бустовский указатель не инвариантен?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
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/... bc80aebaf2

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

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

Кстати, идею обнулять оригинал при изъятии у него права владения, я подглядел у стд::ауто_птр
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
15.11.2011, 15:21 20
Bers, std::auto_ptr не присутствует в новом стандарте. Вместо него shared/weak/scoped etc.
0
15.11.2011, 15:21
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.11.2011, 15:21
Помогаю со студенческими работами здесь

Не знаю как реализовать
Требуется сделать поиск без перезагрузки страницы, то есть: Вбиваешь в поиск и сразу результаты,...

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

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

Canvas - не знаю как реализовать
Добрый день. Помогите пожалуйста по следующим вопросам. 1. Не знаю как реализовать отмену...


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

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

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