c++重写已定义的变量
c++ Overwriting an already defined variable
我有以下主要函数,使用指针创建系数的乘积。这只是该项目的一小部分,用于创建多项式:
#include "header.h"
int main()
{
TermProd x = TermProd( new Coeff(4), new Coeff(8));
x.print(); cout << endl;
x = TermProd( new Coeff(8), new Coeff(15));
x.print(); cout << endl;
return 0;
}
经过测试,覆盖似乎起作用了。但是当我调用x上的print时,我会遇到分段错误。我已经试着盯着它看了很长一段时间,但我搞不清真正的问题。此外,我的搜索没有指向正确的方向,所以我决定创建一个小代码片段来重现错误。
我的header.h文件看起来像:
class Term{
public:
Term(){};
virtual ~Term(){};
virtual Term* clone() const = 0;
virtual void print() const = 0;
};
class Coeff:public Term{
int m_val; //by def: >=0
public:
// Constructor
Coeff();
Coeff(int val = 1):m_val(val)
// Copy constructor
Coeff* clone() const{return new Coeff(this->val());}
// Destructor
~Coeff(){}
// Accessors
int val() const{return m_val;} ;
// Print
void print() const{cout << m_val; }
};
class TermProd:public Term{
TermPtr m_lhs, m_rhs;
public:
// Constructor
TermProd(TermPtr lhs, TermPtr rhs):m_lhs(lhs), m_rhs(rhs){ }
// Copy constructor
TermProd* clone() const
{
return new TermProd(m_lhs->clone(), m_rhs->clone());
}
// Destructor
~TermProd(){ delete m_lhs;delete m_rhs;}
// Accessors
Term* lhs() const { return m_lhs; }
Term* rhs() const { return m_rhs; }
// Print
void print() const
{
cout << "("; m_lhs->print(); cout << '*'; m_rhs->print(); cout << ")";
}
};
注意,这里不是覆盖x
变量,而是分配给它。这将调用您的类型的默认operator=
,这大致会导致执行以下代码
- 执行构造函数
TermProd::TermProd(TermPtr, TermPtr)
- 值
m_lhs
和m_rhs
被复制到值x
中 - 现在运行步骤#1中创建的值的析构函数,并删除
m_lhs
和m_rhs
在这一点上,你有一个真正的问题。在步骤#2之后,值x
和在步骤#1中创建的临时值都共享相同的m_lhs
和m_rhs
值。步骤#3的析构函数删除它们,但是x
仍然有一个对它们的引用,它现在有效地指向死内存
为了解决这个问题,您需要添加自己的operator=
,它可以正确处理赋值语义。例如
TermProd& operator=(const TermProd& other) {
if (&other != this) {
delete m_lhs;
delete m_rhs;
m_lhs = other.m_lhs->clone();
m_rhs = other.m_rhs->clone();
}
return *this;
};
为了对所有场景都正确,你还需要添加一个合适的复制构造函数
TermProd::TermProd(const TermProd& other) :
m_lhs(other.m_lhs->clone()),
m_rhs(other.m_rhs->clone())
{
}
实际上,为了使这变得非常简单,您应该考虑使用std::shared_ptr<Term>
作为TermPtr
的值。这是一个指针,它将使共享在没有上述所有开销的情况下工作。
您没有遵守三条规则
在函数调用期间通过调用隐式复制构造函数delete
创建的临时变量的销毁是分配的指针成员。
您需要提供自己的复制构造函数和复制赋值运算符,它们将对动态分配的指针成员进行深度复制。
您不提供复制构造函数。您有一个clone
方法,注释说它是复制构造函数,但它不是。
试试类似的东西:
TermProd(TermProd const & other)
m_lhs(other.m_lhs->clone()),
m_rhs(other.m_rhs->clone())
{
}
其他班级也是如此。
更新正如评论中所指出的,您还需要赋值运算符。
TermProd & operator=(TermProd const & other)
{
if (this != &other) // Check for assignment to self.
{
delete m_lhs;
delete m_rhs;
m_lhs = other.m_lhs->clone();
m_rhs = other.m_rhs->clone();
}
return *this;
}
相关文章:
- 用C++中的一个变量定义一个常量
- 变量定义到C++布尔值转换
- 未声明的标识符错误,但变量定义正确 (?)
- C++多线程程序:变量定义为类成员的隔离错误
- 将变量定义为静态时,为什么可以多次定义它
- 初始值设定项列表与构造函数赋值与变量定义
- 如何根据传递给函数的变量定义特征矩阵大小
- C++ 描述如何使用来简化变量定义
- 如何转发声明依赖于变量定义的类,而变体定义又依赖于模板化类?
- 是否修改其声明语句中的变量定义良好
- 使用类的其他成员变量定义类的成员变量数组
- 是否可以通过全局变量定义具有可变参数数的函数中的参数数量
- 元组 std::get() 不适用于变量定义的常量
- 全局使用变量定义和C 声明
- C++变量定义中的易失性类型量词位置
- 将变量定义为数组和正确的语法
- 多个,包括具有变量定义的头文件
- 调用构造函数,并将成员作为参数解析为变量定义
- 逗号分隔变量定义中关系前的序列
- 如何使用命名变量定义常量右值引用参数的默认值