C++加法运算符多次重载
C++ addition operator overloading multiple times
我正在尝试使一些数学结构起作用,其中包含 'Cells',它表示具有一组输入和输出的数学函数。
每个数学运算都有自己的 class,它继承自 Cell
。使用一些运算符重载,我想在两个单元格上调用 operator+
时生成一个新的 Add
-Cell。
到目前为止一切正常,但我遇到了问题。
我写了一个小的演示代码来说明我的问题:
想象一下这个 class 完全实现 copy/move assignment/construction 以及自定义析构函数和构造函数。
class Cell{
private:
Cell* A = nullptr;
Cell* B = nullptr;
public:
Cell() {
std::cout << "default constructed" << std::endl;
}
Cell(Cell& A, Cell& B) {
this->A = &A;
this->B = &B;
std::cout << "default constructed" << std::endl;
}
T(const Cell& other){
this->A = other.A;
this->B = other.B;
std::cout << "copy constructed" << std::endl;
}
T(Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "move constructed" << std::endl;
}
Cell& operator=(Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "move assigned" << std::endl;
return *this;
}
Cell& operator=(const Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "copy assigned" << std::endl;
return *this;
}
Cell operator+(Cell& other){
return T{*this, other};
}
virtual ~Cell() {
std::cout << "destructed" << std::endl;
}
};
和我的代码差不多。这里 Cell
可以被认为是具有 2 个先前数学运算的任何类型的单元格。
所以当我尝试做这样的事情时,问题就出现了:
Cell t1{};
Cell t2{};
Cell t3{};
auto h = t1 + t2 + t3;
它创建了 3 个空的 Cell
对象。然后它基于 t1
和 t2
创建一个新的 Cell
并使用它来创建一个新的 Cell
和 t3
。这里的问题是第一个 Cell = t1 + t2
将在该操作后直接被破坏,最后的树将持有无效引用。
这个问题可以通过这样做很容易地解决:
auto h1 = t1 + t2;
auto h = h1 + t3;
或在重载加法运算符 operator+
.
中使用 new
我不想在操作员内部使用 new
,因为清理它们最终只能通过使用某种跟踪系统来实现。
我想知道是否有解决这个问题的好方法。
我很高兴得到任何建议或帮助。
我们有 2021 年,所以使用 C++14
中的 C++11 std::unique_ptr
和 std::make_unique
。
class Cell{
private:
using ptr = std::unique_ptr<Cell>;
ptr A;
ptr B;
public:
Cell() {
std::cout << "default constructed" << std::endl;
}
Cell(Cell&& A, Cell&& B) {
this->A = std::make_unique<Cell>(std::move(A));
this->B = std::make_unique<Cell>(std::move(B));
std::cout << "default constructed" << std::endl;
}
T(Cell&& other){
this->A = std::move(other.A);
this->B = std::move(other.B);
std::cout << "move constructed" << std::endl;
}
Cell& operator=(Cell&& other){
this->A = std::move(other.A);
this->B = std::move(other.B);
std::cout << "move assigned" << std::endl;
return *this;
}
Cell operator+(Cell&& other) && {
return T{std::move(*this), std::move(other)};
}
ptr clone() const {
if (this)
return std::make_unique<Cell>(A->clone(), B->clone());
return nullptr;
}
virtual ~Cell() {
std::cout << "destructed" << std::endl;
}
};
如果您需要实际的复制构造函数赋值,请使用 clone
方法。
或者您可以使用 shared_ptr
,但在这种情况下 Cell
不可变会更安全。
我正在尝试使一些数学结构起作用,其中包含 'Cells',它表示具有一组输入和输出的数学函数。
每个数学运算都有自己的 class,它继承自 Cell
。使用一些运算符重载,我想在两个单元格上调用 operator+
时生成一个新的 Add
-Cell。
到目前为止一切正常,但我遇到了问题。
我写了一个小的演示代码来说明我的问题:
想象一下这个 class 完全实现 copy/move assignment/construction 以及自定义析构函数和构造函数。
class Cell{
private:
Cell* A = nullptr;
Cell* B = nullptr;
public:
Cell() {
std::cout << "default constructed" << std::endl;
}
Cell(Cell& A, Cell& B) {
this->A = &A;
this->B = &B;
std::cout << "default constructed" << std::endl;
}
T(const Cell& other){
this->A = other.A;
this->B = other.B;
std::cout << "copy constructed" << std::endl;
}
T(Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "move constructed" << std::endl;
}
Cell& operator=(Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "move assigned" << std::endl;
return *this;
}
Cell& operator=(const Cell&& other){
this->A = other.A;
this->B = other.B;
std::cout << "copy assigned" << std::endl;
return *this;
}
Cell operator+(Cell& other){
return T{*this, other};
}
virtual ~Cell() {
std::cout << "destructed" << std::endl;
}
};
和我的代码差不多。这里 Cell
可以被认为是具有 2 个先前数学运算的任何类型的单元格。
所以当我尝试做这样的事情时,问题就出现了:
Cell t1{};
Cell t2{};
Cell t3{};
auto h = t1 + t2 + t3;
它创建了 3 个空的 Cell
对象。然后它基于 t1
和 t2
创建一个新的 Cell
并使用它来创建一个新的 Cell
和 t3
。这里的问题是第一个 Cell = t1 + t2
将在该操作后直接被破坏,最后的树将持有无效引用。
这个问题可以通过这样做很容易地解决:
auto h1 = t1 + t2;
auto h = h1 + t3;
或在重载加法运算符 operator+
.
new
我不想在操作员内部使用 new
,因为清理它们最终只能通过使用某种跟踪系统来实现。
我想知道是否有解决这个问题的好方法。
我很高兴得到任何建议或帮助。
我们有 2021 年,所以使用 C++14
中的 C++11 std::unique_ptr
和 std::make_unique
。
class Cell{
private:
using ptr = std::unique_ptr<Cell>;
ptr A;
ptr B;
public:
Cell() {
std::cout << "default constructed" << std::endl;
}
Cell(Cell&& A, Cell&& B) {
this->A = std::make_unique<Cell>(std::move(A));
this->B = std::make_unique<Cell>(std::move(B));
std::cout << "default constructed" << std::endl;
}
T(Cell&& other){
this->A = std::move(other.A);
this->B = std::move(other.B);
std::cout << "move constructed" << std::endl;
}
Cell& operator=(Cell&& other){
this->A = std::move(other.A);
this->B = std::move(other.B);
std::cout << "move assigned" << std::endl;
return *this;
}
Cell operator+(Cell&& other) && {
return T{std::move(*this), std::move(other)};
}
ptr clone() const {
if (this)
return std::make_unique<Cell>(A->clone(), B->clone());
return nullptr;
}
virtual ~Cell() {
std::cout << "destructed" << std::endl;
}
};
如果您需要实际的复制构造函数赋值,请使用 clone
方法。
或者您可以使用 shared_ptr
,但在这种情况下 Cell
不可变会更安全。