gpt4 book ai didi

c++ - 我们可以继承自 Qt 容器吗?

转载 作者:太空狗 更新时间:2023-10-29 20:26:53 25 4
gpt4 key购买 nike

我们是否应该能够继承 Qt 容器,例如 QListQVectorQMap,以便专门化它们并添加功能?如果是这样,我们需要做什么才能确保容器正常工作(虚拟方法、虚拟析构函数等?)。如果没有,为什么不,我还有哪些其他选择?

最佳答案

STL 和 Qt 容器都选择非虚拟析构函数。

有一个有趣的讨论为什么会这样,以及为什么 Qt5 没有修复它。

此外,请注意 STL 样式和 Qt 容器之间的进一步区别。在他的博客文章中引用 Jens Weller An introduction into Qt :

Still, there is an important difference between Qt containers and STL containers: Qt containers have value semantics, and will only perform copy on write, while a std container will copy its full contents when copied. This behavoir accounts for most of Qt base classes, that they will only create a new instance for data, when needed. This implicit sharing of resources is a very important concept to understand when dealing with Qt and its containers.

您的选择一如既往:

  • 作文

    例如

     struct MyFancyList
    {
    QList<MyType> _data;

    bool frobnicate() { return true; }
    };
  • 免费功能

    例如用非成员操作扩展 QList:

    template <typename> bool frobnicate(QList<T>& list)
    {
    // your algorithm
    return true;
    }

如果您真的想做一些有趣的事情,例如创建隐式转换或重载成员运算符,您可以求助于表达式模板。

更新:后者也是QStringBuilder采取的做法在新版本中。见

奖金

为了好玩,这里有一个(糟糕的!)说明如何使用表达式模板扩展 std::stack<T> 的接口(interface).看吧Live on Coliruideone

众所周知,std::stack不模拟顺序容器,因此没有begin() , end() , 或 operator[]定义。通过一些技巧,我们可以定义一个 eDSL 来提供这些功能,而无需组合或继承。

为了真正说明您可以以基本方式“重载”包装类的行为,我们将做到这一点,以便您可以隐式转换 extend(stack)[n] 的结果。到 std::string ,即使堆栈包含例如int .

#include <string>
#include <stack>
#include <stdexcept>

namespace exprtemplates
{
template <typename T> struct stack_indexer_expr
{
typedef std::stack<T> S;
S& s;
std::size_t n;
stack_indexer_expr(S& s, std::size_t n) : s(s), n(n) {}

operator T() const {
auto i = s.size()-n; // reverse index
for (auto clone = s; !clone.empty(); clone.pop())
if (0 == --i) return clone.top();
throw std::range_error("index out of bounds in stack_indexer_expr");
}

operator std::string() const {
// TODO use `boost::lexical_cast` to allow wider range of T
return std::to_string(this->operator T());
}
};

template <typename T> struct stack_expr
{
typedef std::stack<T> S;
S& s;
stack_expr(S& s) : s(s) {}

stack_indexer_expr<T> operator[](std::size_t n) const {
return { s, n };
}
};
}

现在我们所要做的就是播种我们的表达式模板。我们将使用包装任何 std::stack 的辅助函数:

template <typename T> 
exprtemplates::stack_expr<T> extend(std::stack<T>& s) { return { s }; }

理想情况下,我们的用户永远不会意识到 exprtemplates 中的确切类型命名空间:

#include <iostream>
int main()
{
std::stack<double> s;
s.push(0.5);
s.push(0.6);
s.push(0.7);
s.push(0.8);

std::string demo = extend(s)[3];
std::cout << demo << "\n";
}

瞧。更多疯狂:

auto magic = extend(s);
std::cout << magic[0] << "\n";
std::cout << magic[1] << "\n";
std::cout << magic[2] << "\n";
std::cout << magic[3] << "\n";

double as_double = magic[0];
std::string as_string = magic[0];

打印

0.5
0.6
0.7
0.8

免责声明

  1. 我知道 std::stack有一个限制性的接口(interface)是有原因的。
  2. 我知道我的索引实现效率惊人。
  3. 我知道隐式转换是邪恶的。这只是一个人为的例子。
  4. 在现实生活中,使用 Boost::Proto 来启动 DSL。手动完成所有机械操作有很多陷阱。

QStringBuilder以获得更真实的生活样本。

关于c++ - 我们可以继承自 Qt 容器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17929735/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com