通过多态性和指针C++自定义异构容器
C++ custom heterogeneous container through polymorphism and pointers
我正在围绕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
的operator[]
(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
,而是在做upcast
。data
类是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
是可以容忍的,如果我错了,请纠正我。而且我真的很愿意知道你对这个解决方案的批评和赞赏,因为它可以帮助我作为初学者学到更多。
谢谢。
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 使用自定义工具集获取动态退出析构函数链接错误 - eh 矢量析构函数
- DIRECTX9 中自定义顶点的虚拟析构函数
- 仅在删除包含对象的向量时调用自定义»析构函数«
- 这个递归类需要一个自定义析构函数?
- C++ - 定义自定义析构函数时程序崩溃
- 自定义向量类的解构函数
- 使用自定义析构函数时出现"Undefined reference"错误
- std::unique_ptr的自定义deleter是手动调用析构函数的有效位置吗
- `不可复制`与自定义析构函数
- 是否可以使用 std::shared_ptr 创建共享对象池,并在没有自定义析构函数的情况下创建weak_ptr
- 自定义字符串类和析构函数
- 使用自定义分配器调用对象构造函数/析构函数
- 通过多态性和指针C++自定义异构容器
- 如何以"二维方式"使用 boost::variant 定义异构 std::map
- 为什么只有在声明了自定义构造函数时,基类析构函数才能访问
- 带有Placement New的自定义析构函数