Как вывести тип производного класса

Допустим, у меня есть базовый абстрактный класс:

class Base
{
public:
virtual ~Base(){};
};

и выведенный из него шаблон класса:

template<typename T>
class Derived : public Base
{
public:
void function();
};

И еще один класс Test, который имеет вектор объектов Базового класса

 class Test
{
public:
vector< Base* > base_vector;
};

ВОПРОС 1: Если у нас есть вектор указателей на объекты базового класса, они также могут быть заполнены указателями на производные классы, верно?

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

void (Test test)
{
vector<Base*> objects = test.base_vector;
}

ВОПРОС 2: Можно ли вывести типовое имя производных объектов, на которые указывают указатели? (Производный класс является шаблоном)

ИЛИ Можно ли вызвать функцию (), определенную в классе Derived, и не заботиться о типе класса Derived?

Если нет, то какие минимальные изменения следует внести в любой из этих классов?

1

Решение

Если я правильно понимаю вашу проблему, то вам нужно использовать виртуальные функции. Если вы хотите вызвать функцию для объектов и убедиться, что вызывается функция правильного типа, сделайте function виртуальная. Так что вы должны объявить это в своем Base учебный класс. Кроме того, вы должны сделать свой вектор вектором указателей на Base, Затем, когда вы звоните function для объектов вектора он вызовет функцию из производного класса, если объекты действительно имеют производный тип.

Таким образом, вам не нужно узнавать тип объектов, вы просто вызовете виртуальную функцию, и она выяснит, какой это тип объекта, и вызовет правильную функцию.

1

Другие решения

Я не уверен, что понял, что вы хотите, но подойдет ли вам эта модификация вашего кода? Таким образом, вам либо вообще не нужно выводить тип, либо вы можете получить виртуальный type() метод, который вернет вам перечисление с некоторым уникальным значением для каждого типа.

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

class Base {
public:
virtual void function() = 0;
virtual ~Base() = default;
};

template <class T> class Derived : public Base {
public:
void function() override {
// to produce some output
std::cout << typeid(T).name() << std::endl;
}
};

class Test {
public:
std::vector<std::unique_ptr<Base>> objects;
};

int main() {
Test test;
test.objects.push_back(std::make_unique<Derived<int>>());
test.objects.push_back(std::make_unique<Derived<std::string>>());
for (auto &ptr : test.objects) {
ptr->function();
}
}

Альтернативное решение этой проблемы заключается в использовании variant класс, например повышение :: вариант, или std :: эксперимент :: вариант (если он есть в стандартной библиотеке). Таким образом, вам не нужно иметь virtual function() в базовом классе. boost::variant имеет which() метод, который возвращает вас и целое число типа в списке типов. Пример:

#include <boost/variant.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Base {
public:
virtual ~Base() = default;
};

template <class T> class Derived : public Base {
public:
void function() {
std::cout << typeid(T).name() << std::endl;
}
};

class Test {
public:
std::vector<boost::variant<Derived<int>, Derived<std::string>>> objects;
};

int main() {
Test test;
test.objects.push_back(Derived<int>());
test.objects.push_back(Derived<std::string>());
for (auto& obj : test.objects) {
switch (obj.which()) {
case 0:
boost::get<Derived<int>>(obj).function();
break;
case 1:
boost::get<Derived<std::string>>(obj).function();
break;
}
}
return 0;
}
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector