如何在不知道基础类型的情况下从模板化父类中获取值?

时间:2017-04-19 21:40:25

标签: c++ templates polymorphism

鉴于这些定义和一些代码用于说明目的:

class Child
{
    private:
    std::string name;

    public:
    Child(const std::string & name) name(name)
    { }
}

template<typename T>
class Parent : public Child
{
    private:
    T data;

    public Parent(const std::string & name, const T & data) : Child(name), data(data)
    { }

    inline GetData() const
    {
        return this->data;
    }
}

std::vector<std::unique_ptr<Child>> values;
values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));

for (const auto & v : values)
{
    // I want to access the int and string here!
}

如何从基类中确定父类中使用的类型?

我正在使用的具体方案实际上是我有一堆SqlParameterBase类,其中包含有关存储过程的SQL参数的信息以及应该包含在SqlParameter<T>模板中的std::vector<std::unique_ptr<SqlParameterBase>>模板{1}}并传递给表示存储过程配置的类,以便可以调用它。

但这里的基本问题是我需要访问底层数据,我想避免在基类中定义void *以包含指向数据的指针。我希望它尽可能安全。

我也愿意采用其他设计或方法来解决这个问题,所以如果你觉得它更好,请随意提出完全不同的建议。

2 个答案:

答案 0 :(得分:0)

试试这个程序(对于这个问题:我如何从基类中确定父类中使用的类型?):

输出打印类型.. 但是需要做更多的工作才能看起来更好

value a of type:i
value b of type:NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

这里“i”表示第一行中的整数。

第二个中有“basic_string”。但是它周围有些垃圾。

我发布这个是因为它可能会引发更好的想法。

为修改的代码添加了注释。

//g++  5.4.0

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

//CREATED ANOTHER VARIABLE AND FUNCTION FOR TYPENAME.
//MODIFIED CONSTRUCTOR ACCORDINGLY.
class Child 
{
    private:
    std::string name;
    std::string tyName;

    public:
    Child(const std::string & name,const std::string &tyname):name(name), tyName (tyname)
    { }

    std::string  getName()
    {
        return name;
    }

    std::string  getTypeName()
    {
        return tyName;
    }
};

//MODIFIED CONSTRUCTOR TO PASS THE TYPENAME TO PARENT CLASS.
template<typename T>
class Parent : public Child
{
     private:
     T data;

     public:
     Parent(const std::string & name, const T & data) : Child(name,typeid(data).name()), data(data) 
     { }

     inline T GetData() const
     {
           return this->data;
       }
};



int main()
{
    std::vector<std::unique_ptr<Child>> values;
    values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
    values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));


    //GET THE POINTER OF YOUR BASE CLASS.
    //PRINT THE TYPE NAME.
    for (const auto & v : values)
    {
        Child *p = dynamic_cast<Child*>(v.get());
        std::cout<<p->getName()<<" of type:"<<p->getTypeName()<<std::endl;        
    }

    return 0;
}

答案 1 :(得分:0)

您希望仅在派生类型中存在的子承诺功能(返回类型化数据)。在继承下,这是抽象功能。所以一组推测的虚拟访问器。这里并不需要向上倾斜。

我会说。如果你不希望Child承诺它返回什么,只是它返回某些东西然后你的界面看起来太广泛了,你就把界面放在代替消耗界面的代码中,比如说与投机演员等。

可以通过Child中定义的接口来连接一组Child,或者它们具有仅在Derived中可用的某些特殊功能,并且必须以这种方式说出。

作为一个小附录,您可能会考虑std::vector<std::variant<type1, type2, ...>>而不是完全错误地修改容器中的类型信息? std :: variant是C ++ 17 ofc所以可能不合适,但有第三方实现 - boost变体等。