通过多态性和指针C++自定义异构容器

C++ custom heterogeneous container through polymorphism and pointers

本文关键字:自定义 异构 C++ 指针 多态性      更新时间:2023-10-16

我正在围绕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;}
};

recordoperator[](inline data* operator [](ushort field);(允许我以这种方式访问基data类:

db::str* mys = dynamic_cast<db::str*>((*record)[3]);

和编译:g++ -o main -lsqlite3 main.cpp 在 Arch Linux 下,编译没有问题。但是当我运行它时,我会Segmentation Fault.

注释掉dynamic_cast行让我感到高兴,但我个人认为我在某种程度上做错了,而不是认为data类的定义或使用存在问题。

我也感谢对我的代码的任何激进冒犯,因为我知道我是一个新手。非常感谢。

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

你不是在做downcast,而是在做upcastdata类是operator[]返回的基,你把它投射给db::str*,这是一个子类。并非每个data都是str,因此对于初学者来说,您应该检查您要投射的是否是str以及投射是否不返回 0。

此外,您应该习惯使用 Valgrind,尤其是它的 memcheck 工具。您可能会在几秒钟内确定位置和原因,作为 Arch 用户,我向您保证它在存储库中。您使用 valgrind --tool=memcheck ./myprogram 运行程序。

感谢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是可以容忍的,如果我错了,请纠正我。而且我真的很愿意知道你对这个解决方案的批评和赞赏,因为它可以帮助我作为初学者学到更多。

谢谢。