存储派生对象的映射

时间:2016-04-30 16:41:42

标签: c++ inheritance dictionary polymorphism

我有父类:

class Data
{
    public:
        Data ( void ) { }
        Virtual int Size ( void ) 
        {
            return 100;
        }
    protected:
        map<string, Data*> m;

};

从类Data继承的类:

class Struct : public Data
{
    public: 
        Struct ( void ) { }
        Struct & Add ( const string & name, Data x )
        {
            Data * tmp = new Data ( x );
            m[name] = tmp;
            return *this;
        }
        void Print ( void ) 
        {
            for ( const auto & tmp : m )
                cout << tmp . first << "    " << tmp . second -> Size () << endl;
        }
};

class IntData : public Data
{
    public:
        IntData ( void ) { }
        int Size ( void )
        {
            return 4;
        }
};

class DoubleData : public Data
{
    public:
        DoubleData ( void ) { }
        int Size ( void )
        {
            return 8;
        }

};

主要:

int main ( void )
{
    Struct  a;
    a . Add ( "Integer",IntData () );
    a . Print ();
    return 0;
}
Current output : Integer 100
Expected output : Integer 4

我想创建一个地图,它可以容纳从Data类派生的各种类型的对象。但是当我想从map中的存储对象调用方法Size(在本例中为IntData)时应该返回4它始终从父类Data返回值。我该怎么办呢?

2 个答案:

答案 0 :(得分:4)

你的问题是:

        Data * tmp = new Data ( x );

您放入地图的实际指针是Data父类的实例。您将从您通过值传递的参数中复制构造Data父类的新实例作为参数。

您需要将整个功能更改为:

    Struct & Add ( const string & name, Data *x)
    {
        m[name] = x;
        return *this;
    }

调用者现在负责构造任何子类的新实例:

    a . Add ( "Integer",new IntData);

然后,这将按预期工作。

当然,这种方法会带来内存泄漏等各种问题......因此,您最好使用std::shared_ptr。但这将是一个不同的问题......

答案 1 :(得分:1)

我已经为您重写了代码。

#include <unordered_map>
#include <memory>
#include <iostream>

class Data {
    public:
        virtual ~Data(){}
        virtual int Size() = 0;
};

class Struct : public Data {
            std::unordered_map<std::string, std::unique_ptr<Data>> m;
    public: 
        Struct& Add(const std::string& name, std::unique_ptr<Data> x) {
            m[name] = std::move(x);
            return *this;
        }
        void Print() {
            for(const auto& tmp : m )
                std::cout << tmp.first << "    " << tmp.second->Size() << "\n";
        }
        int Size() override {
            int sum = 0;
            for (const auto& tmp : m)
                sum += tmp.second->Size();
            return sum;
        }
};

class IntData : public Data {
    public:
        int Size( ) override { return 4; }
};

class DoubleData : public Data {
    public:
        DoubleData( ) { }
        int Size( ) override { return 8; }
};

int main() {
    Struct  a;
    a.Add("Integer", std::make_unique<IntData>() );
    a.Print();
}

Your welcome.

相关问题