共享_ptr的向量的C 动态降低

C++ dynamic downcasting of a vector of shared_ptr

本文关键字:动态 向量 ptr 共享      更新时间:2023-10-16

编辑:

基本上,我要实现的目标是实现我可以通过任何属性进行排序的卡片。属性可以是整数,双重或其他类型的属性,并且可以在较小的''或"更好"时"更好"。我想到的当前设计是将属性向量用于卡片对象并超载<能够对卡进行排序的操作员。


我正在尝试找出一种存储在向量中的降低shared_ptr元素的方法。目前,我需要尝试所有可能的类型,以铸造适当的类型。

我的问题是我想支持多种类型,而我当前的方法不是很可扩展。据我所读到的运行时不可能获得类型,但是我认为可能有一种聪明的方法可以通过容器类或类似的方法来实现这一目标。

这是我到目前为止的代码(请参阅卡类中的print_attributes()函数)。

#include <iostream>
#include <fstream>
#include <memory>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
class AttributeIface{
    //TODO: Why when the class is empty the casts doesnt work??
    public:
        virtual ~AttributeIface() = default;
};
template <typename T>
class AttributeBase : public AttributeIface{
    private:
        T value;
    public:
        AttributeBase(T value):
            value(value){ }
        virtual ~AttributeBase() = default;
        virtual bool operator<(const AttributeBase<T>* &a) const = 0;
        T get_value(void) const{
            return value;
        }
        void print_value(void){
            cout << value << endl;
        }
};
template <typename T>
class AttributeGreaterThan : public AttributeBase<T>{
    public:
        AttributeGreaterThan(T value):
            AttributeBase<T>(value){ }
        bool operator<(const AttributeBase<T>* &a) const{
            return this->get_value() > a->get_value();
        }
};
template <typename T>
class AttributeLessThan : public AttributeBase<T>{
    public:
        AttributeLessThan(T value):
            AttributeBase<T>(value){ }
        bool operator<(const AttributeBase<T>* &a) const{
            return this->get_value() < a->get_value();
        }
};
class Card{
    private:
        vector<tuple<string,shared_ptr<AttributeIface>>> attribute;
    public:
        Card(){
            //TODO: Examples to get rid of
            attribute.push_back(make_tuple("test",
                                           make_shared<AttributeGreaterThan<int>>(123)));
            attribute.push_back(make_tuple("test2",
                                           make_shared<AttributeGreaterThan<double>>(2.3)));
            attribute.push_back(make_tuple("test3",
                                           make_shared<AttributeLessThan<int>>(321)));
            attribute.push_back(make_tuple("test4",
                                           make_shared<AttributeLessThan<double>>(3.4)));
        }
        void print_attributes(void){
            for(tuple<string,shared_ptr<AttributeIface>> &a : attribute){
                //TODO: How can I get rid of these if/elif?
                if(dynamic_pointer_cast<AttributeGreaterThan<int>>(get<1>(a))){
                    cout << get<0>(a) << " is a 'gt' int with value => " <<
                        dynamic_pointer_cast<AttributeGreaterThan<int>>(get<1>(a))->get_value() << endl;
                }
                else if(dynamic_pointer_cast<AttributeGreaterThan<double>>(get<1>(a))){
                    cout << get<0>(a) << " is a 'gt' double with value => " <<
                        dynamic_pointer_cast<AttributeGreaterThan<double>>(get<1>(a))->get_value() << endl;
                }
                else if(dynamic_pointer_cast<AttributeLessThan<int>>(get<1>(a))){
                    cout << get<0>(a) << " is a 'lt' double with value => " <<
                        dynamic_pointer_cast<AttributeLessThan<int>>(get<1>(a))->get_value() << endl;
                }
                else if(dynamic_pointer_cast<AttributeLessThan<double>>(get<1>(a))){
                    cout << get<0>(a) << " is a 'lt' double with value => " <<
                        dynamic_pointer_cast<AttributeLessThan<double>>(get<1>(a))->get_value() << endl;
                }
            }
        }
};
int main(int argc, char** argv){
    Card card;
    card.print_attributes();
    return 0;
}

这是我在堆栈溢出上的第一个问题,因此请不要犹豫,告诉我我的问题不清楚或需要更多详细信息。

谢谢!

您不能使用动态铸件来实现这一目标。您可以使用的是虚拟函数:

class AttributeIface{
    public:
        virtual void print_value() = 0;
};
cout << get<0>(a) << " has value => ";
get<1>(a)->print_value();
cout << 'n';

我将作为一个练习来打印中间模板的名称。


//TODO: Why when the class is empty the casts doesnt work??

由于动态铸造只能与多态性类型一起使用,并且如果基部没有虚拟功能,则它不是多态。