简体   繁体   中英

Function Overloading with Shared Pointers

I had expected this to work but during compiling I get an error, if anyone can point out my mistake or how I should resolve it would be much appreciated. Preferably without resorting to casts. Is there a standard design pattern to do this?

I made a simplified example of my code that shows the problem and my intentions. I have a (normally abstract) base class (shape) with derived classes (Square, Circle). I have shared_ptr references to the objects and want to execute the according functions in a different calls based on the shared_ptr type.

Below is the code that is not working and short of doing dynamic type casting and an ugly if statement I do not know how to correct it.

//Standard includes
#include "memory"
#include <typeinfo>

class Shape
{
public:
    virtual ~Shape() = default;
};
class Circle : public Shape { };
class Square : public Shape { };

class Logging
{
    static void print(std::shared_ptr<Circle> shape)
    {
        std::cout << "This object is a " << typeid(*shape).name() << std::endl;
    }

    static void print(std::shared_ptr<Square> shape)
    {
        std::cout << "This object is a " << typeid(*shape).name() << std::endl;
    }
};

int main() {
    //Shared Pointer Shape Declaration
    std::shared_ptr<Shape> circle = std::make_shared<Circle>();
    std::shared_ptr<Shape> square = std::make_shared<Square>();

    //Printing Shapes
    Logging::print(circle);     //Compiler ERROR: none of the 2 overloads could convert all the argument types
    Logging::print(square);     //Compiler ERROR: none of the 2 overloads could convert all the argument types

return 0;
}

Thanks in advance for any helpful answers.

Your problem lies in downcasting from std::shared_ptr<Shape> to std::shared_ptr<Circle> . Upcasting when passing to a function, even with smart pointers, is automatic, but not downcasting. So your compiler can't find a print function with this signature:

static void Logging::print(std::shared_ptr<Shape> shape);

And you have an overload error.

But, since you are using the dereference operator ( * ) inside your function, and since std::shared_ptr overload this operator, you can bypass this signature error by using a template member function:

Variant of Logging print() function:

class Logging
{
    public:
    template <class T>
    static void print(std::shared_ptr<T> shape)
    {
        std::cout << "This object is a " << typeid(*shape).name() << std::endl;     
    }
};

Here is the example working . Just remember that when using templates, that if you are working with smart pointers, use the signature std::shared_ptr<T> .

This way, you can avoid using static and dynamic casts.

Although Shape and Square are related types, std::shared_ptr<Shape> and std::shared_ptr<Square> are not . That's why there is not any implicit cast between them, so you get a compiler error.

A very classic solution to this would be to delegate the print logic to each class derived from Shape:

#include "memory"
#include <typeinfo>
#include <iostream>

class Shape
{
public:
    virtual ~Shape() = default;
    virtual void print() {}; // empty implementation, you could make it pure virtual as well
};
class Circle : public Shape { 
public:
    virtual void print() override {
        std::cout << "This object is a circle" << std::endl;
    }
};
class Square : public Shape { 
public:
    virtual void print() override {
        std::cout << "This object is a square" << std::endl;
    }
};

class Logging
{
public:
    static void print(std::shared_ptr<Shape> shape) {
        shape->print();
    }
};

int main() {
    //Shared Pointer Shape Declaration
    std::shared_ptr<Shape> circle = std::make_shared<Circle>();
    std::shared_ptr<Shape> square = std::make_shared<Square>();

    //Printing Shapes
    Logging::print(circle);
    Logging::print(square);

    return 0;
}

Working example

Note that this is just an example and depending on your actual problem this implementation could not be practical/optimal.

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