Как узнать какой подкласс скрывается за ссылкой на базовый класс
Есть класс узла, который может иметь родительский и дочерние узлы. У него есть метод для получения дочернего узла по его имени
Node& Node::getChild(std::string name)
{
//...
}
От класса узла можно наследовать другие подклассы. Но в данной ситуации неизвестно какой конкретный подкласс скрывается за базовым классом.
Как узнать что именно скрывает возвращаемая ссылка?
Сделать метод виртуальным не вариант...
Ответы (2 шт):
Во-первых то что вы хотите невозможно, во-вторых не нужно. Дело в том, что подобные проблемы решаются с помощью паттерна visitor.
Зависит от того, в каком виде вы хотите получить информацию о производном классе. Если нужно знать совпадает ли тип с каким-то конкретным наследником, чтобы использовать методы этого наследника, то достаточно использовать dynamic_cast.
Если нужно просто идентифицировать наследника, то может помочь оператор typeid:
#include <iostream>
#include <typeinfo>
struct B {
virtual ~B() = default;
};
struct D : B {};
struct FF : B {};
int main()
{
B& ref1 = *new D;
B& ref2 = *new FF;
std::cout << std::boolalpha;
try {
dynamic_cast<D&>(ref1);
std::cout << "ref1 is D\n";
}
catch (...) {
std::cout << "ref1 isn't D\n";
}
try {
dynamic_cast<D&>(ref2);
std::cout << "ref2 is D\n";
}
catch (...) {
std::cout << "ref2 isn't D\n";
}
std::cout << typeid(ref1).name() << "\n";
std::cout << typeid(ref2).name() << "\n";
}
Вывод:
ref1 is D
ref2 isn't D
1D
2FF
Строки, возвращаемые через typeid::name не являются стандартизированными, но на уровне определённого компилятора можно добиться подходящего результата. В данном случае видно, что строка состоит из числа, задающего кол-во символов имени, и последующего за ним имени.
При всём этом не стоит забывать, что и typeid и dynamic_cast для работы требуют наличия хотя бы одной виртуальной функции в базовом классе. В моем примере для этого выбран виртуальный деструктор.