简体   繁体   中英

Polymorphism with smart pointers using templates

I'm having trouble putting a shared_ptr of sf::Text, sf::Sprite and sf::Text into an array of shared_ptr
sf::Drawable is the mother class of all the above and is abstract
Here's the game engine function:

GameEngine.h

template<class T>
    void add(std::shared_ptr<T> actor);

GameEngine.cpp

template<>
void GameEngine::add<sf::Drawable>(std::shared_ptr<sf::Drawable> actor)
{
    drawables.insert(actor);
}

Rendering.cpp

void Rendering::addDrawable(std::shared_ptr<sf::Sprite> sprite, sf::Vector2i texture_rect, const char* texture_name)
{
    sf::Texture* _texture = engine.lock()->getGameData().getTexture(texture_name);
    if (_texture) {
        sprite->setTexture(*_texture);
        sprite->setTextureRect(sf::IntRect(0, 0, texture_rect.x, texture_rect.y));
        //What do i have to put in the below function?
        engine.lock()->add(sprite);
    }
}

I'm getting the following error in VS 2015:

1>Rendering.obj : error LNK2019: symbole externe non résolu "public: void __thiscall GameEngine::add<class sf::Sprite>(class std::shared_ptr<class sf::Sprite>)" (??$add@VSprite@sf@@@GameEngine@@QAEXV?$shared_ptr@VSprite@sf@@@std@@@Z) référencé dans la fonction "public: void __thiscall Rendering::addDrawable(class std::shared_ptr<class sf::Sprite>,class sf::Vector2<int>,char const *)" (?addDrawable@Rendering@@QAEXV?$shared_ptr@VSprite@sf@@@std@@V?$Vector2@H@sf@@PBD@Z)
1>Rendering.obj : error LNK2019: symbole externe non résolu "public: void __thiscall GameEngine::add<class sf::Shape>(class std::shared_ptr<class sf::Shape>)" (??$add@VShape@sf@@@GameEngine@@QAEXV?$shared_ptr@VShape@sf@@@std@@@Z) référencé dans la fonction "public: void __thiscall Rendering::addDrawable(class std::shared_ptr<class sf::Shape>,char const *)" (?addDrawable@Rendering@@QAEXV?$shared_ptr@VShape@sf@@@std@@PBD@Z)
1>Rendering.obj : error LNK2019: symbole externe non résolu "public: void __thiscall GameEngine::add<class sf::Text>(class std::shared_ptr<class sf::Text>)" (??$add@VText@sf@@@GameEngine@@QAEXV?$shared_ptr@VText@sf@@@std@@@Z) référencé dans la fonction "public: void __thiscall Rendering::addDrawable(class std::shared_ptr<class sf::Text>,char const *,char const *,class sf::Color)" (?addDrawable@Rendering@@QAEXV?$shared_ptr@VText@sf@@@std@@PBD1VColor@sf@@@Z)

Is there a way to put a shared pointer of a subclass into an array of shared pointers of its mother class?

EDIT:
An answer said that:

Just because Sprite is a subclass of Drawable, does not mean that shared_ptr<Sprite> is a subclass of shared_ptr<Drawable> .

Then why can i do this?

class A{};

class B : public A {};

int main() {
    std::vector<std::shared_ptr<A>> ar;
    ar.push_back(std::make_shared<B>());
    return 0;
}

Just because Sprite is a subclass of Drawable , does not mean that shared_ptr<Sprite> is a subclass of shared_ptr<Drawable> .

When the compiler sees this:

engine.lock()->add(sprite);

it looks for a member function add(shared_ptr<sf::Sprite>) following the overload resolution rules.

Even though shared_ptr<Sprite> is not a subclass of shared_ptr<Drawable> , there is an implicit conversion available, so it would be a candidate.

However this:

template<class T>
    void add(std::shared_ptr<T> actor);

provides a declaration of the function for any type, but no definition . Therefore it provides an exact match and will be chosen by the compiler. That is why you get linker errors.

One way to solve this is to use std::static_pointer_cast , like this:

engine.lock()->add(std::static_pointer_cast<Drawable>(sprite));

I would also reconsider if/why you need the template above - I can't see what purpose that is serving, other than to give you link time errors instead of compile time errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM