如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
What will explode if I really, really want to inherit from an STL container, and I inherit the constructors and delete the new operator?
假设我违背了我在这个网站和网上其他地方找到的所有建议,做了这样的事情:
#include <vector>
#include <array>
#include <iostream>
using PointType = std::array<double, 3>;
class Point
:
public PointType
{
public:
using PointType::PointType;
Point(const Point& copy)
:
PointType(copy)
{
std::cout << "Point(const Point&)" << std::endl;
}
Point(Point&& rval)
:
PointType(rval)
{
std::cout << "Point(Point&&)" << std::endl;
}
// Prevent PolygonType* p = new Polygon; delete p;
template<typename ...Args>
void* operator new (size_t, Args...) = delete;
};
using PolygonType = std::vector<PointType>;
class Polygon
:
public PolygonType
{
public:
using PolygonType::PolygonType;
Polygon(const Polygon& copy)
:
PolygonType(copy)
{
std::cout << "Polygon(const Polygon&)" << std::endl;
}
Polygon(Polygon&& rval)
:
PolygonType(rval)
{
std::cout << "Polygon(Polygon&&)" << std::endl;
}
// Prevent PolygonType* p = new Polygon; delete p;
template<typename ...Args>
void* operator new (size_t, Args...) = delete;
};
如果我对从不使用new与Point
或Polygon
或类似类型一起使用感到满意,那么删除new
运算符可以解决未定义行为的问题:
std::array<double, 3> a = new Point({1., 2., 3.})
delete a;
对std::vector<PointType>
施加的算法施加的条件是相同的:算法检查公共接口是否符合算法中所做的工作。如果我希望算法(函数模板(将此点向量视为线段的开放链或闭合多边形,这是一个问题。这排除了在解析函数模板候选项时依赖隐式接口的情况。此外,概念在到达时对我没有帮助,因为容器上的条件是相同的,我希望算法对它们执行的操作不同。因此,另一方面,如果我使用 SFINAE 使用 SFINAE 进行标记调度,则使用type_traits
中的新元函数来检查模板参数是否已使用特定标记,则使用这样的具体类型并标记它们会使标记调度变得微不足道。
此外,重新键入构造函数的旧问题也随着 C++11 构造函数继承而消失。
那么,当以继承构造函数并删除new
运算符的方式从 STL 继承时,什么仍然会爆炸?一定有什么我没有看到的。
如果你的对象总是静态或自动分配(没有new
(,那么它将以相同的方式被破坏,所以你不需要虚拟析构函数,所以这将按预期工作。
从标准容器衍生并不是完全禁止的,它只是危险。您似乎通过消除危险的用例在很大程度上减轻了危险。
请注意,如果您确实允许动态分配,然后通过指向基的指针删除,即使派生类没有自己的状态(即没有成员(,您仍然拥有 UB。对象生存期比仅计算数据成员要复杂得多。
您仍然可以允许动态分配,并且永远不要通过指向基的指针进行删除,但这在逻辑上是否适合您,更不用说足够的保护了,仅取决于上下文。
轶事:我偶尔会从"库代码"中的向量/映射继承,不打算被其他人进一步扩展。它不是开源软件,它是我控制下的专有代码库,所以自由使用评论很好。如果你想通过容器的整个界面,组合有点痛苦。
- 通过继承类使用来自不同命名空间的运算符
- 运算符继承和 cpp 核心准则 c.128 的问题
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 继承模板化转换运算符
- C++ 继承运算符=
- 在继承的模板类中使用下标 [] 运算符
- 如何调用继承的重载运算符<<并在派生类的输出中添加更多文本?
- C++模板化类上继承的运算符'<<'
- 类继承和运算符重载
- 通过继承重载运算符会导致歧义
- 使用继承的指针列表复制构造函数或重载运算符=
- C++中移动赋值运算符的继承
- 如何在C++上的多个继承上下文上使用特定基类中的运算符
- 继承类中的比较运算符
- 继承 C++14 中的模板化运算符 =:g++ 和 clang++ 的不同行为
- 具有继承的未声明标识符(运算符 ostream)
- 如何使用运算符编写可继承的模板类
- C++继承运算符<<
- 继承运算符 +()
- 继承运算符*的问题