Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Преобразование умных указателей 
V
    Опции темы
volk666
Дата 1.6.2011, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 1.6.2011

Репутация: нет
Всего: нет



class A {...}
class B : public A {...}

std::tr1::shared_ptr< A > a(new B());
std::tr1::weak_ptr< B > b;
b = a; // не компилируется
Как можно сделать преобразование от предка к потомку для умных указателей?
Нужно для списка классов, порожденных от A(возможно, абстрактного).
Заранее спасибо.
PM MAIL   Вверх
afiskon
Дата 1.6.2011, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



Код

class A {
public:
    virtual void getName() {
        cout << "This is A!" << endl;
    }
};

class B: public A {
public:
    virtual void getName() {
        cout << "This is B!" << endl;
    }
};

// ............

    shared_ptr<A> aptr(new B);
    weak_ptr<B> bptr;

    bptr = static_pointer_cast<B>(aptr);
    bptr.lock()->getName();

PM MAIL WWW   Вверх
cupper
Дата 1.6.2011, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(volk666 @ 1.6.2011,  18:53)
class A {...}
class B : public A {...}

std::tr1::shared_ptr< A > a(new B());
std::tr1::weak_ptr< B > b;
b = a; // не компилируется
Как можно сделать преобразование от предка к потомку для умных указателей?
Нужно для списка классов, порожденных от A(возможно, абстрактного).
Заранее спасибо.

а ты ничего не напутал ? преобразование вниз по иерархии это совсем плохая практика. 

Ты и просто на указателя такую штука так просто не сделаешь
Код

class A {public: A(){}};
class B : public A {public: B(){}};

int main()
{
   A* a = new B();
   B* b;
   
   b = a;
}

Код

source.cpp: In function 'int main()':
source.cpp:14:8: error: invalid conversion from 'A*' to 'B*' [-fpermissive]

Build finished with errors


тут нужно либо пользоваться хардкорными кастами (типа static_cast, или какой то другой). Либо хм... а других способов и не припомню я.
PM MAIL   Вверх
afiskon
Дата 1.6.2011, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



Цитата

а ты ничего не напутал ? преобразование вниз по иерархии это совсем плохая практика. 

Обычная практика, если не забывать делать деструкторы виртуальными.

Код

    B b;
    A* a = &b; // B является A
    //B* pb = a; // обратное _не_всегда_ верно...
    B* pb = static_cast<B*>(a); // но мы то с вами знаем!
    pb->getName();

ЗЫ. А еще в вашем коде память течет ;)

Добавлено через 4 минуты и 47 секунд
Цитата

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

А что, простите, "хардкорного" в static_cast?
PM MAIL WWW   Вверх
cupper
Дата 1.6.2011, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(afiskon @ 1.6.2011,  22:19)
Цитата

а ты ничего не напутал ? преобразование вниз по иерархии это совсем плохая практика. 

Обычная практика, если не забывать делать деструкторы виртуальными.

А что, простите, "хардкорного" в static_cast?

http://alenacpp.blogspot.com/2005/08/c.html первый абзац абзац наиболее четко описывает то что я хотел сказать.

Раскройте мне секрет как связано преобразования вниз по иерархии и виртуальные деструкторы ?
PM MAIL   Вверх
volk666
Дата 2.6.2011, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 1.6.2011

Репутация: нет
Всего: нет



afiskon, большое спасибо smile ! Как раз это и было нужно. Надо tr1 и boost получше изучить. Тема закрыта.
Цитата

а ты ничего не напутал ? преобразование вниз по иерархии это совсем плохая практика. 

Это смотря что делаешь. Есть список объектов базового класса, обрабатывается алгоритмом. В то же время каждый элемент этого списка - свойство других объектов, но уже как производный класс. У каждого элемента есть ID, по которому он находится, и его тип заранее известен ==> никаких ошибок не будет.


Это сообщение отредактировал(а) volk666 - 2.6.2011, 00:15
PM MAIL   Вверх
afiskon
Дата 2.6.2011, 13:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



cupper Это у вас такой хитрый троллинг? smile

Цитата

Лучшая практика по приведению типов: не делать этого. Потому что, если в программе потребовалось приведение типов, значит в этой программе с большой долей вероятности что-то неладно.

Я так могу про что угодно написать:
Цитата

Лучшая практика по использованию protected-методов: не делать этого. Потому что, если в программе потребовались protected-методы, значит в этой программе с большой долей вероятности что-то неладно.

или:
Цитата

Лучшая практика по использованию оператора new: не делать этого. Потому что, если в программе потребовался оператор new, значит в этой программе с большой долей вероятности что-то неладно.

1. ПОЧЕМУ?
2. Даже если new в теории небезопасен (забыл сказать delete - и память потекла), это не значит, что его никогда-никогда не нужно использовать. Например, любая фабрика использует new. Не использовать теперь фабрики? Другой вопрос, что с умными указателями программа будет надежнее.

Цитата

как связано преобразования вниз по иерархии и виртуальные деструкторы ?

Пожалуйста:

Код

A* createSomething(/* args */) {
  B* pb = new B;
  return pb;
}

A* pa = createSomething(/* args */);
/// ....
delete pa; // если деструктор не виртуальный, вызовет ~A, когда нужно ~B!


Тут идет преобразование вниз (а вообще низ и верх иерархии - вещи относительные, родителей обычно рисуют сверху), но если у нас имеет место наслодование A -> B -> C, то мы можем создать C, вернуть его, как A, потом кастнуть в B и вызвать не тот деструктор ~B, когда нужен ~C. 

А вообще советую вам почитать Майерса, у него вопросы, что вы задаете, очень хорошо освещены.

Это сообщение отредактировал(а) afiskon - 2.6.2011, 13:48
PM MAIL WWW   Вверх
cupper
Дата 2.6.2011, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(afiskon @ 2.6.2011,  13:42)
А вообще советую вам почитать Майерса, у него вопросы, что вы задаете, очень хорошо освещены.

А сами то читали :?

Цитата

Правило 27: Не злоупотребляйте приведением типов

Правила C++ разработаны так, чтобы неправильно работать с типами было 
невозможно. Теоретически, если ваша программа компилируется без ошибок, 
значит, она не пытается выполнить никаких небезопасных или бессмысленных 
операций с объектами. Это ценная гарантия. Не надо от нее отказываться.
К сожалению, приведения обходят систему типов. И это может привести
к различным проблемам, некоторые из которых распознать легко, а некоторые -
чрезвычайно трудно. Если вы пришли к C++ из мира С, Java или С#, примите
эток сведению, поскольку в указанных языках в приведениях типов чаще 
возникает необходимость, и они менее опасны, чем в C++. Но C++ - это не С. Это не
Java Это не С#. В этом языке приведение - это средство, к которому нужно 
относиться с должным почтением.


сейчас начнете, что есть ситуации когда нужно... и бла бла бла, тогда возвращайся к посту на блог Алены, и
Цитата

Потому что, если в программе потребовалось приведение типов, значит в этой программе с большой долей вероятности что-то неладно.


Жаль нет Страуструпа в электронке под рукой, еще бы и на него сослался. Боюсь что бестолку.

И кстати, указатели это зло, зловещее зло smile страшен тот код где работа идет только с голыми указателями. Это как бриться скальпелем пьяным на намыленном полу. Код должен быть прост и не вызывать вопросов.

Это сообщение отредактировал(а) cupper - 2.6.2011, 21:54
PM MAIL   Вверх
boostcoder
Дата 2.6.2011, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(cupper @  2.6.2011,  21:28 Найти цитируемый пост)
Потому что, если в программе потребовалось приведение типов, значит в этой программе с большой долей вероятности что-то неладно.

полагаю, динамический полиморфизм Вам не известен. smile

Добавлено через 2 минуты и 34 секунды
вообще-то, afiskon истину глаголит.

а работать с сырыми указателями, или со смартами - это не ошибка или нарушение правил - это выбор smile 
PM WWW   Вверх
afiskon
Дата 2.6.2011, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



cupper, одно дело избегать (Майерс) и не использовать (Алёна C++ в вашей интерпретации). Я согласен с тем, что использование указателей по возможности нужно сводить к минимуму. Меньше шансов выстрелить себе в ногу. Но с 
Цитата

преобразование вниз по иерархии это совсем плохая практика. 

или
Код

И кстати, указатели это зло, зловещее зло

согласиться не могу. Если вы так не любите указатели, пишите на Haskell, там их вообще нет. Ни одного. В принципе.
PM MAIL WWW   Вверх
cupper
Дата 3.6.2011, 11:42 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Я ей богу не понимаю почему вы плюшки ООП приписываете к кастам. Я бы мог щас расписать принципы ооп, накой хер нужны динамические полиморфизмы и виртуальные деструкторы... но вы и так должны это знать. Единственно чего я не понимаю - причем тут касты и все это. Каст это всего лишь преобразования типа но не стандартное (которое умеет делать сам компилятор, например от потомка к предку) а то ответственность за которое полностью и бесповоротно несет сам программист. А это лишний повод для ошибки.

Если в задаче появляется необходимость привести указатель предка к указателя на потомка для того что бы вызвать функции потомка, получается что у вас потомки совсем таки разные получаются. И смысл унаследовать их от родителя как бы и теряется. Так как они не дополняют а изменяют базовый класс. У Майерса про ето как раз очень хорошо написано, не помню в какой именно книже, толи советы по С++? толи по STL. 

PS. исправил ошибки.

Это сообщение отредактировал(а) cupper - 3.6.2011, 13:45
PM MAIL   Вверх
afiskon
Дата 3.6.2011, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



Трудно в чем-то убедить человека, когда он этого не хочет smile
PM MAIL WWW   Вверх
boostcoder
Дата 3.6.2011, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(cupper @  3.6.2011,  11:42 Найти цитируемый пост)
Если в задаче появляется необходимость привести указатель на базовый класс к указателя на предка для того что бы вызвать функции потомка, получается что у вас потомки совсем таки разные получаются. И смысл унаследовать их от родителя как бы и теряется.

пичалька smile

Добавлено через 2 минуты и 10 секунд
хотел было привести пример стандартной ситуации когда это нужно(возможно это единственный способ при динамическом полиморфизме), но не стану...
как уже сказал afiskon:
Цитата(afiskon @  3.6.2011,  11:43 Найти цитируемый пост)
Трудно в чем-то убедить человека, когда он этого не хочет


PM WWW   Вверх
cupper
Дата 3.6.2011, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(boostcoder @ 3.6.2011,  11:45)
хотел было привести пример стандартной ситуации когда это нужно

Пример в студию !
PM MAIL   Вверх
boostcoder
Дата 3.6.2011, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Код

#include <vector>
#include <memory>
#include <iostream>

struct base {
   virtual void method() = 0;
};

struct derived1: base {
   virtual ~derived1() {}
   virtual void method() { std::cout << "derived1" << std::endl; }
};

struct derived2: base {
   virtual ~derived2() {}
   virtual void method() { std::cout << "derived2" << std::endl; }
};

typedef std::shared_ptr<base> base_ptr;
typedef std::vector<base_ptr> impls_list;

int main() {
   impls_list list;
   list.push_back(base_ptr(new derived1)); // каст!
   list.push_back(base_ptr(new derived2)); // и еще один!
   
   list[0]->method();
   list[1]->method();
}

http://liveworkspace.org/code/bf5e12a26406...b9cf0c8731596c8

покажи способ сделать это не используя каст по иерархии ;)
на примере динамического полиморфизма.

зы
хотя я предпочитаю статический.
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0849 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.