使用共享指针的函数重载
Function Overloading with Shared Pointers
我原以为这会起作用,但在编译过程中出现错误,如果有人能指出我的错误或我应该如何解决,将不胜感激。最好不要诉诸演员表。是否有标准的设计模式可以做到这一点?
我做了一个简化的代码示例来显示问题和我的意图。我有一个(通常是抽象的)基础 class(形状)和派生的 classes(方形,圆形)。我有 shared_ptr 对对象的引用,并希望在基于 shared_ptr 类型的不同调用中执行相应的函数。
下面是无法正常工作的代码,缺少动态类型转换和丑陋的 if 语句,我不知道如何更正它。
//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;
}
提前感谢您提供任何有用的答案。
虽然Shape
和Square
是相关类型,但std::shared_ptr<Shape>
和std::shared_ptr<Square>
不是。这就是为什么它们之间没有任何隐式转换,所以你会得到一个编译器错误。
一个非常 classic 的解决方案是将打印逻辑委托给从 Shape 派生的每个 class:
#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;
}
请注意,这只是一个示例,根据您的实际问题,此实现可能不是 practical/optimal。
您的问题在于从 std::shared_ptr<Shape>
向下转换为 std::shared_ptr<Circle>
。传递给函数时向上转型,即使使用智能指针,也是自动的,但不是向下转型。所以你的编译器找不到带有这个签名的打印函数:
static void Logging::print(std::shared_ptr<Shape> shape);
而且你有一个过载错误。
但是,由于您在函数内部使用了取消引用运算符 (*
),并且由于 std::shared_ptr
重载了该运算符,因此您可以使用 template
绕过此签名错误成员函数:
Logging
print()
函数的变体:
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。请记住,在使用模板时,如果您使用的是智能指针,请使用签名 std::shared_ptr<T>
.
这样,您就可以避免使用静态和动态转换。
我原以为这会起作用,但在编译过程中出现错误,如果有人能指出我的错误或我应该如何解决,将不胜感激。最好不要诉诸演员表。是否有标准的设计模式可以做到这一点?
我做了一个简化的代码示例来显示问题和我的意图。我有一个(通常是抽象的)基础 class(形状)和派生的 classes(方形,圆形)。我有 shared_ptr 对对象的引用,并希望在基于 shared_ptr 类型的不同调用中执行相应的函数。
下面是无法正常工作的代码,缺少动态类型转换和丑陋的 if 语句,我不知道如何更正它。
//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;
}
提前感谢您提供任何有用的答案。
虽然Shape
和Square
是相关类型,但std::shared_ptr<Shape>
和std::shared_ptr<Square>
不是。这就是为什么它们之间没有任何隐式转换,所以你会得到一个编译器错误。
一个非常 classic 的解决方案是将打印逻辑委托给从 Shape 派生的每个 class:
#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;
}
请注意,这只是一个示例,根据您的实际问题,此实现可能不是 practical/optimal。
您的问题在于从 std::shared_ptr<Shape>
向下转换为 std::shared_ptr<Circle>
。传递给函数时向上转型,即使使用智能指针,也是自动的,但不是向下转型。所以你的编译器找不到带有这个签名的打印函数:
static void Logging::print(std::shared_ptr<Shape> shape);
而且你有一个过载错误。
但是,由于您在函数内部使用了取消引用运算符 (*
),并且由于 std::shared_ptr
重载了该运算符,因此您可以使用 template
绕过此签名错误成员函数:
Logging
print()
函数的变体:
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。请记住,在使用模板时,如果您使用的是智能指针,请使用签名 std::shared_ptr<T>
.
这样,您就可以避免使用静态和动态转换。