- 构造
- 拷贝构造
- 赋值操作符
- 析构
1.前面的代码
#include<iostream>
using namespace std;
class Shape
{
private:
int no;
};
inline void
Point::setX(int ix){x = ix;}
inline void
Point::setY(int iy){y = iy;}
inline void
Point::getX(){return x;}
Point::getY(){return y;}
class Rectangle:public Shape
{
private:
int width;
int height;
Point* leftUp;
public:
Rectangle(int width,int height,int x,int y);
Rectangle(const Rectangle& other);
Rectangle& operator = (const Rectangle& other);
~Rectangle();
int getWidth();
int getHeight();
};
Rectangle::Rectangle(int width,int height,int x,int y):width(width),height(height)
{
leftUp = new Point();
leftUp ->setX(x);
leftUp->setY(y);
}
- leftUp = new Point()并不是很好,最好写在成员初始化列表里,效率好。
2.拷贝构造函数问题
Rectangle::Rectangle(const Rectangle& other)
{
this->height = other.height;
this->width = other.width;
delete leftUp;
this->leftUp = new Point();
this->leftUp = setX(other.leftUp->getX());
this->leftUp = setY(other.leftUp->getY());
}
- delete leftUp问题
- leftUp开始的时候是一个随机值—对象,变量,指针未初始化,刚开始在局部变量或者类成员中是一个随机值,即上一次内存留下的原生内存的值
- 野指针,幽灵指针…
- delete一个0或者null没有问题
- 行为未定义—在实际程序中,可能指向正在使用中的对象,delete后会导致程序崩溃,在《Effective C++》里面有一定的描述。
this->leftUp = setX(other.leftUp->getX());
this->leftUp = setY(other.leftUp->getY());
Q:
- this->leftUp = new Point(*other.leftUp)
- 调用父类的拷贝构造函数,显示调用,写在初始化列表中:Shape(other)
- 当leftUp指针为空时,这个时候需要判断。
- 要用到初始化列表
- 初始化顺序根据类的声明顺序,先父类,后子类成员
典型拷贝构造函数:
1. 考虑空值
2.非指针的成员要单独处理
3.{ }里只对指针成员做处理,其它全部放在初始化列表
4.初始化列表里的顺序与你的标准顺序一致
修改后的拷贝构造函数:
Rectangle::Rectangle(const Rectange& other)
:Shape(other),heigth(other.heigth),width(other.width)
{
if(other.leftUp != nullptr){
this->leftUp = new Point(*other.leftUp);
}else
{
this->leftUp = nullptr;
}
}
3.赋值操作符
Rectangle&
Rectangle::operator = (const Rectangle& other)
{
if(this != &other){
this->height = other.height;
this->width = other.width;
delete leftUp;
this->leftUp = new Point();
this->leftUp = setX(other.leftUp->getX());
this->leftUp = setY(other.leftUp->getY());
return *this;
}else{
return *this;
}
}
- 判断是否自我赋值,但是拷贝构造不需要,因为对象还没有创建
- 害怕指针未初始化就delete,此为悬浮指针,但是赋值操作符对象构造完成,无法为悬浮指针。
- 调用父类的赋值操作符—shape::operator = (other);
- 避免悬浮指针—delete后可以赋值nullptr
1.
Rectangle(int width,int height,int x,int y):
Shape(),width(width),height(height),leftUp(new Point(x,y)){}
Shape( )没有必要去写,默认调用父类的构造函数
2.
Rectangle(const Rectangle& other):
Shape(),width(other.width),height(other.height),leftUp(new Point(*other.leftUp)){}
Shape(other)
没有判断other.leftUp是否为空