C ++定制异构容器通过多态和指针

时间:2012-03-29 15:08:10

标签: c++ inheritance casting

我正在围绕sqlite3编写一个非常简单的小包装器,并使用sqlite3_get_table()以char**的形式获取结果。我使用基础数据类来将字段存储在统一容器中,即在此处记录,然后使用派生类型专门获取每种数据类型。

这是我的基类:

class data
{
    private:
        uint sz;
        virtual void abstract() = 0;

    public:
        inline data(char* pd);
        inline data();
        uint size() {return sz;}
};

这是示例派生类:

class str : public data
{
    private:
        string* pdata;
        virtual void abstract() {}

    public:
        inline str(char* pd);
        inline operator string();
        inline operator const char*();
};

和记录类:

class record
{
    private:
        ushort cols;
        data** entries;
    public:
        record(char** ppdata, uint col_count);
        inline data* operator [](ushort field);
        inline uint num_fields() {return cols;}
};

record的{​​{1}}(operator[])允许我以这种方式访问​​基础inline data* operator [](ushort field);课程:

data

并在Arch Linux下编译:{{1​​}},编译时没有问题。但是当我运行它时,我得到db::str* mys = dynamic_cast<db::str*>((*record)[3]);

评论dynamic_cast行让我感到高兴,但我个人认为我在某种程度上做错误,而不是认为定义或使用g++ -o main -lsqlite3 main.cpp类时存在问题。

我也很欣赏我的代码中的任何激进攻击,因为我知道我是新手。非常感谢。

3 个答案:

答案 0 :(得分:1)

当您使用dynamic_cast时,您需要检查结果以查看它是否为NULL。当对象实际上不是您尝试转换为的类型的实例时,会发生这种情况。

答案 1 :(得分:1)

你没有downcast,你正在做upcastdata类是operator[]返回的基础,您将其投射到db::str*,这是一个孩子。并非每个data都是str,因此对于初学者来说,您应该检查您尝试投射的是str以及投射是否不返回0。

此外,您应该习惯使用Valgrind,尤其是memcheck工具。您可以在几秒钟内确定地点和原因,并且作为Arch用户自己,我保证它在回购中。您使用valgrind --tool=memcheck ./myprogram运行程序。

答案 2 :(得分:1)

感谢TC1和Mark Ransom。我试着解决我的问题,我终于意识到这是最好的解决方案,比较它的优点与它的权衡,对于一个简单的包装,就像我正在编写的那样(sqlite3的sqlite3_get_table()):

enum types {INT, FLOAT, STRING, BLOB, NUL};

class bad_type {};

class data
{
    private:
        void* pdata;
        types type;

    public:
        data(int dt)
        {
            int* tmp = new int(dt);
            pdata = static_cast<void*>(tmp);
            type = INT;
        }
        // constructors for other types to be added in a similar fashion.

        operator int()
        {
            if (type == INT)
                return *(static_cast<int*>(pdata));
            throw bad_type();
        }
        // operators for other types to be added in a similar fashion.
};

这样我就使数据*成为一个非常合适的指针类型,用于制作异构容器(很抱歉,当我提出问题时,我不知道这个词;-))在这种情况下,数据类型有限,在这种情况下为5,因为它的工作水平较低。

我刚刚在我的测试main中使用过它:

data* array[3];
array[0] = new data(3);

cout << *(array[0]);

它确实给了我3,当然它也可以将它应用到任何其他类型,特别是在低级别,在这种情况下类型通常是基本的而不是复杂的继承类型。

我开始相信在这种情况下static_cast可以被容忍,如果我错了,请纠正我。此外,我非常愿意了解您对此解决方案的批评和赞赏,因为它有助于我作为初学者学习更多内容。

谢谢。