Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
 Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
Есть либа из одного заголовка tree.h
https://github.com/kpeeters/tree.hh
Все работает и мне удалось загнать в node полиморфный объект и прочитать.
Не удалось кастовать базовый класс к наследнику.
Это код при записи в node string
tree<string>::sibling_iterator sib=tr.begin(loc);
   while(sib!=tr.end(loc)) {
     cout << (*sib) << endl;
     ++sib;
     }

При записи вместо string базового класса и наследника, я получаю базовый так:
MyBase base = *sib;
Как кастовать в наследника его?
27 май 21, 20:03    [22328187]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
Попутный вопрос.
Как работает поиск node в итераторе если ищется не строка а поле класса?
Сейчас при смене типа у меня find не компилится
loc=find(tr.begin(), tr.end(), "two");
27 май 21, 20:07    [22328189]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
Доп.вопрос.
Почему
cout << typeid(base).name() << endl;
Не выводит имя MyBase, а выводит.. (по памяти)
74namespaceMyBase12345
)) компа нет под рукой))
27 май 21, 20:14    [22328197]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
Siemargl
Member

Откуда: 010100
Сообщений: 6493
PetroNotC Sharp,

Кастовать в наследника не нужно. Для этого придумали виртуальные методы
27 май 21, 21:15    [22328236]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
Siemargl
PetroNotC Sharp,

Кастовать в наследника не нужно. Для этого придумали виртуальные методы

Я бы за. Но не вижу специфических методов наследника в IDE.
Они только у наследника.
27 май 21, 21:59    [22328247]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
Siemargl
Member

Откуда: 010100
Сообщений: 6493
PetroNotC Sharp,

Ну ты то умнее IDE... Или нет?
27 май 21, 23:06    [22328262]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
AmKad
Member

Откуда:
Сообщений: 5297
PetroNotC Sharp,

+ Вот, о чем тебе говорил Siemargl
#include <string>
#include "tree.hh"
#include <iostream>
#include <memory>

class Base {
public:
    virtual void Serialize(std::ostream& os) const = 0;
    virtual ~Base() {}
};

auto getTree() {
    class ChildFirst :  public Base { virtual void Serialize(std::ostream& os) const { os << "First"  << std::endl; }; };
    class ChildSecond : public Base { virtual void Serialize(std::ostream& os) const { os << "Second" << std::endl; }; };
    class ChildThird :  public Base { virtual void Serialize(std::ostream& os) const { os << "Third"  << std::endl; }; };
    tree<std::unique_ptr<Base>> mTree;

    mTree.insert(mTree.begin(), std::make_unique<ChildFirst>());
    mTree.insert(mTree.begin(), std::make_unique<ChildThird>());
    mTree.insert(mTree.begin(), std::make_unique<ChildSecond>());

    return mTree;
}

int main() {
    const auto mTree = getTree();
    for (const auto& v : mTree) {
        v->Serialize(std::cout);
    }
    return 0;
}

Second
Third
First

PetroNotC Sharp
Попутный вопрос.
Как работает поиск node в итераторе если ищется не строка а поле класса?
Сейчас при смене типа у меня find не компилится
loc=find(tr.begin(), tr.end(), "two");
std::find_if
28 май 21, 01:06    [22328281]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Спасибо. Круто.
Выше писал что мне нужен НЕ виртуальный метод в наследнике.
Вызов виртуального у меня работает. Там приведение типов не нужно.
Возможно все дело в том что я вместо
mTree.insert(... std::make_unique<ChildFirst>());
по аналогии со строкой
mTree.insert(... "abc" );
Делал
mTree.insert(... ChildFirst(123, "abc") );
Умных указателей развелось.
Доберусь до компа попробую.
28 май 21, 06:57    [22328297]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
Siemargl
PetroNotC Sharp,

Ну ты то умнее IDE... Или нет?
не)))))
Я к IDE отношусь с богопочтением.))
Мне нужно после точки подсказка по кастованному объекту.
28 май 21, 06:59    [22328299]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
автор
Используя информацию о типах во время выполнения, можно проверить, указывает ли указатель на полный объект и можно ли безопасно выполнить приведение этого указателя, чтобы он указывал на другой объект в своей иерархии. Для выполнения этих типов приведений можно использовать оператор dynamic_cast

Вот у меня это не выходило, возможно из за статической инициализации без оператора new объекта.
std::make_unique не приходилось использовать ни разу. Каюсь.
28 май 21, 07:22    [22328305]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Блин))) у меня с++11
Пробовать оператор new?
28 май 21, 10:07    [22328344]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Можно пример для с11?
Ни shared_ptr, ни unique_ptr, ни new не работают.
28 май 21, 10:31    [22328352]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
PetroNotC Sharp
Доп.вопрос.
Почему
cout << typeid(base).name() << endl;
Не выводит имя MyBase, а выводит.. (по памяти)
74namespaceMyBase12345
)) компа нет под рукой))
пишет так
N5my15my213ClassMyE
Для
namespace my1{
namespace my2{
class ClassMy
28 май 21, 10:43    [22328358]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
AmKad
Member

Откуда:
Сообщений: 5297
PetroNotC Sharp

Возможно все дело в том что я вместо
mTree.insert(... std::make_unique<ChildFirst>());
по аналогии со строкой
mTree.insert(... "abc" );
Делал
mTree.insert(... ChildFirst(123, "abc") );
Умных указателей развелось.
Указатель на тип базового класса нужен для вызова виртуальных (полиморфных) методов объектов дочерних классов. Умный он или не очень - в данном контексте не так важно. make_unique появился в C++14, но и до него в C+11 была возможность инициализации умного указателя, правда, в чуть более длинной форме.
28 май 21, 11:01    [22328371]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Пробовал. Не выходит. ((
А с pointer = new class не берет сама либа
28 май 21, 11:12    [22328381]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
AmKad
Member

Откуда:
Сообщений: 5297
PetroNotC Sharp
Пробовал. Не выходит. ((
Ошибка в 17-ой строке.
28 май 21, 11:15    [22328382]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Главное, со статической инициализацией все работает. И я так понял потом кастовать в наш указатель уже поздно что ли?
Я вообще на либу подумал.
Но потом все заработало кроме получения полного класса из базового.
28 май 21, 11:15    [22328383]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad
PetroNotC Sharp
Пробовал. Не выходит. ((
Ошибка в 17-ой строке.
ОК чуть позже все перепроверю.
Спс.
28 май 21, 11:16    [22328384]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Загрузил твой код не в Qt с 11 а в студии
int main() {
    const auto mTree = getTree();
    for (const auto& v : mTree) {
        v->Serialize(std::cout);
  SChildFirst* child = dynamic_cast<ChildFirst*>(v);
         child->f();
    }
    return 0;
}

Дает ошибку cannot convert from unique ptr
Как исправить?
28 май 21, 15:10    [22328494]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
AmKad
Member

Откуда:
Сообщений: 5297
PetroNotC Sharp,

Fix лежит на поверхности, но я не дам тебе решения, пока ты не объяснишь какую задачу ты решаешь и для каких целей тебе такая конвертация.
28 май 21, 15:55    [22328532]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Ну, во первых это обычное поле data pointer в деревьях еще со времен дельфи.
Во вторых, мне конкретно в листьях дерева нужен класс ЛистДерева с бизнес данными.
А выше структура это просто классификатор.
Например, в листьях Семья с атрибутами. А дерево это адрес.
Или
....
Это банальная Модель данных повсюду.
Как поле tag в любом vcl объекте.
28 май 21, 16:08    [22328543]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
Раньше была Сишная конвертация)))
А теперь наворотили из за отсутствия сборщика мусора?
(про shared ptr почитал)))
28 май 21, 16:10    [22328544]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
foreach (var node in tree.nodes) {
    node.Tag as ClassY).functionX()
} 

Это шарп
28 май 21, 16:17    [22328546]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8256
AmKad,
И вообще, чем дерево как коллекция отличается от списка TList?
Я же не о полиморфизме счас.
Там нельзя наследников держать?

Сообщение было отредактировано: 28 май 21, 16:11
28 май 21, 16:19    [22328548]     Ответить | Цитировать Сообщить модератору
 Re: Tree + полиморфный. Как кастовать в наследника?  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6658
PetroNotC Sharp,

Зачем вам наследование если наследники не наследуют виртуальные функции?

Лучше используйте std::vaiant с обычными значениями и не морочьте себе голову.

#include <variant>

struct A {
    void run1() { LOG_TRACE("a"); }
};
struct B {
    void run2() { LOG_TRACE("b");}
};

using Value = std::variant<A, B>;

int main()
{
    tree<Value> tree;
    auto a = tree.insert(tree.begin(), A{});
    tree.append_child(a, B{});
    for (auto&& n: tree) {
        struct Visitor {
            void operator()(A& a)
            {
                a.run1();
            }
            void operator()(B& b)
            {
                b.run2();
            }
        };
        std::visit(Visitor{}, n);
    }
    return 0;
}
28 май 21, 18:08    [22328592]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
Все форумы / C++ Ответить