Как я использую шаблонный класс?

У меня есть пример, подобный приведенному ниже в C ++, где я получаю указатель на базовый класс, exampleParent , и хотел бы привести его к указателю на унаследованный example класса (на самом деле я просто хочу вызвать функцию на example ). Предостережение заключается в том, что унаследованный класс является шаблонным. В приведенном ниже примере я знаю, что шаблон имеет тип int поэтому проблем нет. В общем, что было бы хорошим способом сделать это, если я не знаю заранее тип шаблона?

class exampleParent{};

template<typename P>
class example: public exampleParent
{
public:
    int do_something() const
    { 
        std::cout<<"I am doing something"<<std::endl;
        return 0;
    }
};

boost::shared_ptr<const exampleParent> getPtr()
{
   return boost::make_shared<const example<int>>();
}

int main()
{
    boost::shared_ptr<const exampleParent> example = getPtr();
    auto example_ptr = boost::dynamic_pointer_cast<const example<int>>(example);
    return example_ptr-> do_something();
}

Одно решение, которое я предлагаю, состоит в том, чтобы изменить код на что-то вроде этого:

class exampleParent{};
class something_interface: public exampleParent
{
public:
    virtual int do_something() const = 0 ;
};

template<typename P>
class example: public something_interface
{
public:
    int do_something() const override
    { 
        std::cout<<"I am doing something"<<std::end;
        return 0;
    }
};

boost::shared_ptr<const exampleParent> getPtr()
{
   return boost::make_shared<const example<int>>();
}

int main()
{
    boost::shared_ptr<const exampleParent> example = getPtr();
    auto example_ptr = boost::dynamic_cast<const something_interface>(example);
    return example_ptr->do_something();
}

Это бы сработало, но это кажется чем-то вроде взлома: something_interface самом деле не должно существовать, поскольку само по себе не имеет объектно-ориентированной интерпретации

Любая помощь будет оценена!

Всего 1 ответ


Если вы можете сделать exampleParent абстрактным классом (если вообще можете изменить этот класс), это будет лучшим вариантом:

class exampleParent
{
public:
    virtual ~exampleParent() = default;
    virtual int do_something() const = 0; 
};
template<typename P>
class example: public exampleParent
{
public:
    int do_something() const override
    { 
        std::cout<<"I am doing something"<<std::endl;
        return 0;
    }
};

Тогда вам не нужно приведение, чтобы вызвать этот метод.

Если вы не можете коснуться этого класса exampleParent , перейдите к промежуточному классу, как вы предложили, но не забывайте фактически наследовать exampleParent и не выбрасывать исключение, просто сделайте метод чисто виртуальным:

class intermediate: public exampleParent
{
public:
    ~intermediate() override = default;
    virtual int do_something() const = 0;
};

В противном случае единственный способ - сделать dynamic_pointer_cast для всех возможных типов и проверить результат приведения, потому что разные экземпляры класса шаблона в общем просто разные типы. Конечно, это не имеет смысла, если существует бесконечное количество возможных параметров шаблона P


Есть идеи?

10000