powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Приведение shared_ptr от базового типа к производному и обратно
24 сообщений из 24, страница 1 из 1
Приведение shared_ptr от базового типа к производному и обратно
    #39631015
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть такой код:
Код: plaintext
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.
45.
class B{
public:
int Brightness;
B(): Brightness(100);
};

class D: public B{
public:
int Contrast;
D():
Contrast(200),
B();
};

class С: public B{
public:
int Tone;
C():
Tone(300),
B();
};

void AddTone(std::shared_ptr<C> IndividualSettings)
{
IndividualSettings.Tone++;
}

void AddContrast(std::shared_ptr<D> IndividualSettings)
{
IndividualSettings.Contrast++;
}

void AddBrightness(std::shared_ptr<B> AllSettings, bool UseContrast)
{
AllSettings.Brightness++;

if(UseContrast) AddContrast(AllSettings);//???
else AddTone(AllSettings);//???
}

void main()
{
std::shared_ptr<D> IndividualSettings(std::make_shared<D>);
AddBrightness(IndividualSettings, true); //???
}



Как теперь в вызываемой функции AddBrightness принять значение на базовый класс (потому что это универсальная функция для всех видов настроек)? И как сделать обратное преобразование?
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631023
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLКак теперь в вызываемой функции AddBrightness принять значение на базовый класс (потому
что это универсальная функция для всех видов настроек)?

Измени параметр функции на "B& AllSettings". И избавься от привычки передавать классы по
значению, там лежат укороченные грабли.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631253
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AllSettings.get() вернёт указатель на объект класса шаблонного параметра, его можно (пытаться) кастовать
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631264
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbAllSettings.get() вернёт указатель на объект класса шаблонного параметра, его можно (пытаться) кастовать

Так 100% заработаю ошибку: shared_ptr можно создавать только от new T или на основе другого shared_ptr. Иначе два умных указателя попробуют удалить один и тот же объект: в твоем решении создается два независимых блока подсчета ссылок на объект.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631266
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovИзмени параметр функции на "B& AllSettings". И избавься от привычки передавать классы по
значению, там лежат укороченные грабли.


Так что ли?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void AddBrightness(B& AllSettings, bool UseContrast)
{
AllSettings.Brightness++;

if(UseContrast) AddContrast(AllSettings);//???
else AddTone(AllSettings);//???
}

void main()
{
std::shared_ptr<D> IndividualSettings(std::make_shared<D>);
AddBrightness(IndividualSettings, true); //???
}



Почему- то мне кажется, что 100% не взлетит.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631267
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLshared_ptr можно создавать только от new Tможно, но лучше создавать через make_shared. Раз уж такая тема, то если тебе вдруг понадобилось снять shared_ptr с this, то для этого есть enable_shared_from_this и shared_from_this

AlekseySQLв твоем решении создается два независимых блока подсчета ссылок на объект.в моём решении один shared_ptr, который ты передаёшь в функцию(это у тебя при передаче создаётся второй shared_ptr, и даже иногда именно так и надо делать, но тут не тот случай), а get() - возвращает указатель на объект типа, заданного в шаблоне , а не shared_ptr.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631270
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbAlekseySQLв твоем решении создается два независимых блока подсчета ссылок на объект.в моём решении один shared_ptr, который ты передаёшь в функцию(это у тебя при передаче создаётся второй shared_ptr, и даже иногда именно так и надо делать, но тут не тот случай), а get() - возвращает указатель на объект типа, заданного в шаблоне , а не shared_ptr.

Согласен, что у меня нету ссылки в принимающей функции, и это мой косяк. Но и в твоем решении все также плохо: shared_ptr используют чтобы не следить за временем жизни объекта, чтобы он сам помер когда пропадет в нем необходимость. Если же я получаю сырой указатель (и не имею возможности на его основе создать новый shared_ptr), то все эти плюшки теряются, и я опять должен руками в коде разруливать время жизни объекта. В случае асинхронности (а это мой случай!) решение становится 100% не правильным.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631271
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо, нашел нужные функции преобразования.

Ответ тут .
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631291
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прочитал эту статейку . Там комментаторы сходятся на мысли, что делать указатели на базовый класс для производных объектов при отсутствии виртуальных методов не имеет смысла:
Код: plaintext
1.
2.
3.
4.
5.
class Base {};
class Derived : public Base {};

Base* p = new Derived; // в этом нет никакого смысла
delete p; // так, соответственно, тоже никто делать не будет => виртуальный деструктор не нужен



Но почему? В моем примере есть универсальные настройки (базовый класс) и частные настройки (производные классы). Функции работы с универсальными настройками, принимают указатели на базовый класс. При этом никаких виртуальных функций не используется...

Может у меня говно- style?
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631335
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLНо и в твоем решении все также плохоВ моём решении всё отлично. Ещё раз: я не создаю второй shared_ptr . У тебя в функциях работа с членами-переменными классов A, B и C, вот get() даёт указатель на эти классы, а не новый shared_ptr.
AlekseySQLНо почему?у меня в соседней ветке есть предложение: сделать вывод тестовых сообщений в ctor и dtor и посмотреть самому, что будет.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631336
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если я правильно понимаю ваши терзания, то удаление объекта производного класса через указатель на базовый - неопределённое поведение.
Определённость требует наличия виртуальных функций.
Если в классе нет нужды в виртуальных функциях - объявляется виртуальный деструктор.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631351
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbЕщё раз: я не создаю второй shared_ptr .

А надо.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631353
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovЕсли я правильно понимаю ваши терзания, то удаление объекта производного класса через указатель на базовый - неопределённое поведение.
Определённость требует наличия виртуальных функций.
Если в классе нет нужды в виртуальных функциях - объявляется виртуальный деструктор.

Насколько я понял деструктор не просто "отдувается" из- за необходимости кому- то в классе быть виртуальным, он ОБЯЗАН быть виртуальным, чтобы объекты можно было удалять с помощью указателя на базовый класс.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631532
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как теперь в вызываемой функции AddBrightness принять значение на базовый класс (потому что это универсальная функция для всех видов настроек)? И как сделать обратное преобразование?[/quot]

dynamic_cast
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631537
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЕсли я правильно понимаю ваши терзания, то удаление объекта производного класса через указатель на базовый - неопределённое поведение.
Определённость требует наличия виртуальных функций.
Если в классе нет нужды в виртуальных функциях - объявляется виртуальный деструктор.

Ты опять всё перепутал?

удаление объекта производного класса через указатель на базовый неопределённое поведение, если деструктор базового класса невиртуальный.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631540
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLBasil A. SidorovЕсли я правильно понимаю ваши терзания, то удаление объекта производного класса через указатель на базовый - неопределённое поведение.
Определённость требует наличия виртуальных функций.
Если в классе нет нужды в виртуальных функциях - объявляется виртуальный деструктор.

Насколько я понял деструктор не просто "отдувается" из- за необходимости кому- то в классе быть виртуальным, он ОБЯЗАН быть виртуальным, чтобы объекты можно было удалять с помощью указателя на базовый класс.

Правильно понимаешь.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631555
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если речь идет про shared_ptr, то преобразование от shared_ptr<Derived> к shared_ptr<Base> происходит автоматически, так же как и Derived* к Base*.
А обратное преобразование происходит с помощью std::dynamic_pointer_cast
Код: plaintext
1.
2.
3.
4.
std::shared_ptr<Base> b;
std::shared_ptr<Derived> d;
b = d;
d = std::dynamic_pointer_cast<Derived>(b);



Ну и с простыми указателями
Код: plaintext
1.
2.
3.
4.
Base* b;
Derived* d;
b = d;
d = dynamic_cast<Derived*>(b);
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39631580
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLА надо.Ну, сам себе проблему придумал, сам решил, молодец
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632044
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbAlekseySQLА надо.Ну, сам себе проблему придумал, сам решил, молодец


Shared_ptr создают, чтобы осуществлять совместное владение объектом. Поэтому пользоваться сырым указателем очень опасно: в любой момент объект может уничтожиться, потому что сырой указатель "не застолбил" за собой ссылку. Именно поэтому weak_ptr при проверке преобразуется к shared_ptr, чтобы дальше можно было безопасно работать с объектом.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632061
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLShared_ptr создают, чтобы осуществлять совместное владение объектом...

....разными потоками. Накрайняк - разными объектами с непредсказуемым временем жизни. У
тебя не наблюдается ни того ни другого.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632143
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLв любой момент объект может уничтожитьсяесли у тебя потоки, можно использовать std::atomic или std::mutex. У тебя в коде просто одна итерация. Если ты передаёшь в функцию shared_ptr, то будет сделана копия, счётчик увеличится, и пока ты не покинешь функцию, твой объект не будет уничтожен точно. Поэтому внутри функции нет надобности делать каст с самого shared_ptr, достаточно снять с него указатель на объект класса и работать уже с ним.

Но мне было бы интересно увидеть пример, где необходим каст именно shared_ptr. Раз их сделали, значит они для чего-то понадобились.
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632166
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov....разными потоками. Накрайняк - разными объектами с непредсказуемым временем жизни. У
тебя не наблюдается ни того ни другого.


Ну очевидно, же что в топике приведен всего- навсего пример :)
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632169
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbЕсли ты передаёшь в функцию shared_ptr, то будет сделана копия, счётчик увеличится, и пока ты не покинешь функцию, твой объект не будет уничтожен точно. Поэтому внутри функции нет надобности делать каст с самого shared_ptr, достаточно снять с него указатель на объект класса и работать уже с ним.

Все верно, но при таком подходе надо соблюдать кучу "но", про которые всегда надо помнить:
1. Передавать shared_ptr по значению.
2. После получения сырого указателя не использовать асинхронность.
3. Помнить какой тип производного класса принимает функция (а их может быть много).
4. Не удалять руками shared_ptr (потому что вроде как больше не нужен).
...
Рейтинг: 0 / 0
Приведение shared_ptr от базового типа к производному и обратно
    #39632175
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQL2. После получения сырого указателя не использовать асинхронность.если у тебя есть асинхронные обработки данных, нужно просто правильно их описать или правильно обложить функциями доступа. Иначе есть шанс, что где-нибудь забудешь. Даже если ты сделаешь копию с shared_ptr, данные у тебя могут поменяться, shared_ptr тут проблему асинхронности не решает. И, насколько я понимаю, shared cast тоже не спасёт тебя, если ты принимаешь в функцию ссылку на shared_ptr - его в другом потоке могут убить. Если ты присваивание (к shared_ptr) после каста делаешь - тогда да. Если после каста обращаешься к инкременту - нет.

AlekseySQL3. Помнить какой тип производного класса принимает функция (а их может быть много).в параметрах функции тип виден же? Или что-то другое имелось ввиду?

AlekseySQL4. Не удалять руками shared_ptr (потому что вроде как больше не нужен).да его вообще никогда не надо удалять руками. Даже сбрасывать его требуется крайне редко.

Btw, я когда пишу функцию, я всегда продумываю, что я туда передаю (объект, ссылку, указатель, const) почему и как я там буду с этим работать. Поэтому для меня, например, не проблема держать в голове все "но" :)
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Приведение shared_ptr от базового типа к производному и обратно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]