У меня есть несколько разрозненных шаблонных чистых абстрактных классов. Я извлекаю из них набор классов, и оттуда я могу использовать их для создания группы объектов. Я хотел бы поместить все эти объекты в контейнер. Тем не менее, они все разных типов. Мне интересно, как осуществить этот полиморфизм поздней стадии.
Скажи, что это мой ранее существующий код, который у меня есть сейчас:
#include <iostream>
template<typename T>
class A{
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B{
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
A_example first;
B_example second;
first.printNum();
second.printTwiceNum();
return 0;
}
С большим количеством классов это может стать довольно грязным внутри main()
. В идеале я мог бы просто перебрать контейнер и вызвать print()
для каждого элемента. Моя первая мысль - использовать std::vector<unique_ptr<Base>>
. Это похоже на работу:
#include <iostream>
#include <vector> // new include
#include <memory> // new include
#include <utility> // new include
// new Base class here
class Base{
public:
virtual ~Base(){};
};
template<typename T>
class A : public Base{ // new inheritance here
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B : public Base{ // new inheritance here as well
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
std::vector<std::unique_ptr<Base>> v;
v.emplace_back( new A_example() );
v.emplace_back( new B_example() );
//v[0]->printNum(); // nope
//v[1]->printTwiceNum(); // nope
return 0;
}
Это круто, потому что мне не нужно было менять A_example
или B_example
, и все, что я изменил в A
и B
, это то, что я добавил : public Base
. Тем не менее, я понятия не имею, как вызывать каждый элемент print***
функцию. Есть ли способ вызвать функции printNum()
и printTwiceNum()
и сделать их автоматически распознаваемыми?