Допустим, у меня есть базовый абстрактный класс:
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?
Если нет, то какие минимальные изменения следует внести в любой из этих классов?
Если я правильно понимаю вашу проблему, то вам нужно использовать виртуальные функции. Если вы хотите вызвать функцию для объектов и убедиться, что вызывается функция правильного типа, сделайте function
виртуальная. Так что вы должны объявить это в своем Base
учебный класс. Кроме того, вы должны сделать свой вектор вектором указателей на Base
, Затем, когда вы звоните function
для объектов вектора он вызовет функцию из производного класса, если объекты действительно имеют производный тип.
Таким образом, вам не нужно узнавать тип объектов, вы просто вызовете виртуальную функцию, и она выяснит, какой это тип объекта, и вызовет правильную функцию.
Я не уверен, что понял, что вы хотите, но подойдет ли вам эта модификация вашего кода? Таким образом, вам либо вообще не нужно выводить тип, либо вы можете получить виртуальный 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;
}