最近看了王垠的最新的文章的评论,有一段话:
同样的面试题,有经验的程序员会先把思路说通了再开始写,没经验的程序员会直接写代码,写了几行才发现没想好后面要怎么写。没经验的程序员有一定概率在写完整道题的代码后才发现一个设计缺陷,不可能通过改几行代码修复,必须全部重写。
最近在写程序也是遇到上面所说的问题,对于构造函数,拷贝构造函数,赋值运算,类的组合以及实例化的理解一团糟,因此想在这里理顺一遍。
构造函数(初始化)
Rectangle类中定义了一个指向Point的指针leftUp,我们可以利用这个指针来对(x,y)进行构造赋值。指针leftUp是指向Point类的,但是只是定义,需要我们在堆中去创建它并且实例化,才能对成员x,y进行赋值。
关于实例化的拓展
在面向对象的编程中,通常把用类创建对象的过程称为实例化。
其格式:
类名 对象名 = new 类名(参数1, 参数2, …);
如 Date date=new Date();就是用日期类创建了一个日期的对象,就叫对象的实例化。多数语言中,实例化一个对象 就是为对象开辟内存空间,或者是不用声明,直接使用 new 构造函数名(),建立一个临时对象。
this->leftUp = new Point(x, y);
调用Point的默认构造函数进行传x,y的值。
拷贝构造函数
在C++中,下面三种对象需要调用拷贝构造函数:
1) 一个对象作为函数参数,以值传递的方式传入函数体;
2) 一个对象作为函数返回值,以值传递的方式从函数返回;
3) 一个对象用于给另外一个对象进行初始化(常称为赋值初始化);
//copy ctor
inline
Rectangle::Rectangle(const Rectangle& other)
:Shape(other),width(other.width),height(other.height)
{
if(other.leftUp != nullptr)
{
this->leftUp = new Point(*other.leftUp);
}
else
{
this->leftUp = nullptr;
}
}
赋值操作符
if(this == &other)
{
return *this;
}
如果赋值操作就是本身,直接返回。
//assignment operations
inline
Rectangle& Rectangle::operator=(const Rectangle& other)
{
if(this == &other)
{
return *this;
}
Shape::operator=(other);
this->width = other.width;
this->height = other.height;
if(other.leftUp != nullptr)
{
delete leftUp;
leftUp = new Point(*other.leftUp);
}
else
{
delete leftUp;
this->leftUp = nullptr;
}
return *this;
}
在写赋值构造函数的时候需要考虑到父类,以及other的leftUp指针以及自身leftUp指针为空的情况。
this->leftUp = new Point(*other.leftUp);
当我们在把other.leftUp指向新的对象的时候我们需要对原来的空前进行清空,这样才能有效防止内存泄漏。