有没有办法编写模板函数来处理智能指针和常规指针?

Posted

技术标签:

【中文标题】有没有办法编写模板函数来处理智能指针和常规指针?【英文标题】:is there a way to write a template function for dealing with smart pointer and regular pointer? 【发布时间】:2021-08-24 16:09:14 【问题描述】:

请我尝试编写一个接受智能指针或常规指针向量的函数,但它永远不会工作,我想编写函数getLargestRadius() 接受作为参数std::vector<something*>std::vector<std::shared_ptr<something>>。 它对我有用的唯一方法是重载函数 这是我的完整代码,可以准确理解我的意思:

#include <iostream>
#include <vector>
#include <memory>

class Point

private:
    int m_x 0 ;
    int m_y 0 ;
    int m_z 0 ;

public:
    Point() = default;
    Point(int x, int y, int z)
        : m_xx, m_yy, m_zz
    

    

    friend std::ostream& operator<<(std::ostream &out, const Point &p)
    
        out << "Point(" << p.m_x << ", " << p.m_y << ", " << p.m_z << ')';
        return out;
    
;

class Shape

public:
    virtual std::ostream& print(std::ostream &out) const = 0;

    friend std::ostream& operator <<(std::ostream &out, const Shape &shape)
    
        return shape.print(out);
    
    virtual ~Shape() 
;

class Triangle : public Shape

private:
    Point m_a;
    Point m_b;
    Point m_c;
public:
    Triangle(const Point &a, const Point &b, const Point &c)
        : m_aa, m_bb, m_cc
    
    virtual std::ostream& print(std::ostream &out) const override
    
        out << "Trinagle(";
        out << m_a << ", ";
        out << m_b << ", ";
        out << m_c << ")";
        return out;
    

;
class Circle: public Shape

private:
    Point m_center;
    int m_radius;

public:
    Circle(const Point &center, int radius)
        : m_centercenter, m_radiusradius
    
    

    virtual std::ostream& print(std::ostream &out) const override
    
        out << "Circle(" << m_center << ", radius " << m_radius << ')';
        return out;
    

    int getRadius() const return m_radius;
;


int getLargestRadius(std::vector<std::shared_ptr<Shape>> &v)

    int largestRadius  0 ;

    for(int x0; x < static_cast<int>(v.size()); ++x)
    
            if (dynamic_pointer_cast<Circle>(v[x]))
        
            if (dynamic_cast<Circle&>(*v[x]).getRadius() > largestRadius)
                largestRadius = dynamic_cast<Circle&>(*v[x]).getRadius();
        
    

    return largestRadius;


int getLargestRadius(std::vector<Shape*> &v)

    int largestRadius  0 ;

    for(int x0; x < static_cast<int>(v.size()); ++x)
    
            if (dynamic_cast<Circle*>(v[x]))
        
            if (dynamic_cast<Circle*>(v[x])->getRadius() > largestRadius)
                largestRadius = dynamic_cast<Circle*>(v[x])->getRadius();
        
    

    return largestRadius;

int main()


    std::vector<std::shared_ptr<Shape>> v1 
        std::make_shared<Circle>(Point1, 2, 3, 7),
        std::make_shared<Triangle>(Point1, 2, 3, Point4, 5, 6, Point7, 8, 9),
        std::make_shared<Circle>(Point4, 5, 6, 3)
    ;

    std::vector<Shape*> v2
      new CirclePoint1, 2, 3, 7,
      new TrianglePoint1, 2, 3, Point4, 5, 6, Point7, 8, 9,
      new CirclePoint4, 5, 6, 3
    ;

    for(auto &element : v1)
        std::cout << *element << '\n';


    std::cout << "The largest radius is: " << getLargestRadius(v1) << '\n';
    std::cout << "The largest radius is: " << getLargestRadius(v2) << '\n';

    for(auto &element : v2)
        delete element;

    return 0;

我尝试将其作为模板,但没有任何效果。 如您所见,我必须重载该函数才能使其与两种向量类型一起使用 那么有没有办法使用模板使其只有一个函数适用于所有类型。

谢谢

【问题讨论】:

【参考方案1】:

如果不检查,您可能会使用template

template <typename T>
int getLargestRadius(const std::vector<T>& v)

    int largestRadius  0 ;

    for (const auto& shapePtr : v)
    
        if (const auto* circle = dynamic_cast<const Circle*>(&*shapePtr))
        
            largestRadius = std::max(largestRadius , circle->radius);
        
    

    return largestRadius;

为了平等对待常规指针和智能指针,我尊重它们 (*shapePtr),所以我有一个参考。

(那我需要取回正则指针,所以我取地址&amp;*shapePtr)。

【讨论】:

非常感谢它确实有效,我只是觉得你错过了 type circle->getRadius() ,请你解释一下你为什么使用 &*e ? 我只想强调一下您如何使用取消引用的结果来获取 OP 的利益。

以上是关于有没有办法编写模板函数来处理智能指针和常规指针?的主要内容,如果未能解决你的问题,请参考以下文章

2017/03/17学习笔记

C++智能指针类模板

Item 45:使用成员函数模板来接受所有兼容的类型

c++三种智能指针以及相关知识自写智能指针

智能指针和异常

C++ 智能指针和指针到指针输出 API。模板化的“包装器”