Как я использую шаблонный класс? - PullRequest
1 голос
/ 28 марта 2020

У меня есть пример, подобный приведенному ниже, в 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 Ответ

2 голосов
/ 28 марта 2020

Если вы можете сделать 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;
    }
};

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...