博览网_C++_第二周_Rectangle类的初步实现(一)

来源:互联网 发布:淘宝怎么发布图片 编辑:程序博客网 时间:2024/05/17 03:10

喜欢的朋友可以关注收藏一下:  http://blog.csdn.net/qq_31201973

本文实现了一个Rectangle类型,原版要求如下:

为 Rectangle 类实现构造函数,拷贝构造函数,赋值操作符,析构函数。

class Shape{                      int no;};              class Point{   int x;   int y;};              class Rectangle: public Shape{   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();         };
  首先我的整体规划是class类的声明及对他的操作函数都写在头文件里,cpp里只放main()函数。而不是通常我们常见的声明放在头文件,cpp里放定义和main()函数。这么做的理由是我把整个class Rectangle类当做一个抽象封装,里面有对它的定义、操作、和依赖,我的程序里因为时间关系并没有写进位的依赖关系,但留下了扩展的余地,待以后扩展后再给大家分享后续操作。考虑到头文件中包含的头文件,和cpp中包含的头文件冲突,我采用了以下保护措施。
#ifndef __DATE_H__  #define __DATE_H__        #endif  
Rectangle类是由shape类派生出来的类该类包含三个成员变量width宽,height高,Point类型的指针变量leftUp (leftUp包含两个成员x,y为坐标),因为三个成员变量为private,外部函数无法访问他,所以我给Rectangle定义了三个成员函数get_width() get_height() get_leftUp(),返回width,height,Point的值。同时也给Point定义两个成员函数get_x() get_y() ,来返回x,y的值。

class Point{private:int x;int y;public:int get_x() const { return x; }int get_y() const { return y; }};class Rectangle : public Shape{private:int width;int height;Point * leftUp;public:Rectangle(int width1, int height1, int x1, int y1);//构造函数Rectangle(const Rectangle& other);//拷贝构造函数Rectangle& operator=(const Rectangle& other);//拷贝赋值函数~Rectangle();//析构函数 只声明不定义会出无法解析的错误int get_width() const { return width; }int get_height() const { return height; }Point* get_leftUp() const { return leftUp; }};
  然后就是为Rectangle类定义构造函数,构造函数是定义的时候为对象赋初值,我定义了两个构造函数分为普通构造函数和拷贝构造函数。

1.普通构造函数 a(),就是用默认参数构造。

2.拷贝构造函数 a(b),就是先构造b,把b的参数传给a构造a 。

  先来说普通构造函数,我采用初始化列表的方式初始化,前两个赋值没有什么问题,第三个成员是Point的指针你开始我用leftUp->x(x1);  方法赋值,结果发现成员变量不指明默认为private,如果用 leftUp->get_x() 来访问的话会因为返回的为值不能作为左值,所以我采用了深度拷贝的方法:leftUp(new Point(x1, y1))  ,因为用到了Point的构造,我为Point写了一个构造函数。

Point(int x1, int y1) : x(x1), y(y1){  }//构造函数,支持指针类型深度拷贝
这样Rectangle类的构造函数就可以正常初始化了

inline Rectangle::Rectangle(int width1, int height1, int x1, int y1) : width(width1), height(height1), leftUp(new Point(x1, y1))//深度拷贝,需要Point有构造函数{;}
然后为了测试Rectangle类的构造函数,我定义了一个<<重载函数

ostream& operator<<(ostream& os, guo::Rectangle& str){return os << '(' << str.get_height() << ',' << str.get_width() << ',' << str.get_leftUp()->get_x() << ',' << str.get_leftUp()->get_y() << ')' << endl;}
然后测试的时候出现了这样的错误:



原因是windows.h里和Rectangle冲突,最初因为vs显示窗口一闪而过,我采用 system("pause"); 停一下。

解决方法有两种:

1.用getchar()代替system("pause") 。

2.把所有的类定义到命名空间中

namespace guo{}
这个问题解决以后又出现了新的问题:


这个问题的原因是只在类中声明了析构函数,没有定义它,造成无法解析的错误,解决完这个问题后就可以正常使用了。

#include<iostream>#include"Rectangle.h"#include<Windows.h>//这个头文件中包含类似Rectangle的东西,会使Rectangle无法定义对象using namespace std;//using guo::Point;//using guo::Shape;//using guo::operator<<;ostream& operator<<(ostream& os, guo::Rectangle& str){return os << '(' << str.get_height() << ',' << str.get_width() << ',' << str.get_leftUp()->get_x() << ',' << str.get_leftUp()->get_y() << ')' << endl;}int main(){guo::Rectangle r1(1,1,1,1);//构造函数定义法cout <<"r1="<< r1;system("pause");//头文件 Windows.h ,因为vs2013不会自动添加增加  mov ah,1  int 21H mov ax,4C00H  int 21H   所以屏幕一闪而过。//getchar();//也可以用这个函数等待输入一个字符来让程序等待,缺点是如果有输入,很容易不好用,所以建议用命名空间解决该问题return 0;}
然后定义析构函数,析构函数是对象声明周期结束的时候调用。因为深度拷贝采用的是堆内存,堆内存是自定义的需要用delete释放,如果指向该内存的指针为栈内存变量,而栈内存变量生命周期结束以后由系统收回,那么堆内存没有指向的指针,该内存无法收回就造成了内存泄漏,该析构函数只用调用一次delete就可以。

inline Rectangle::~Rectangle(){delete[] leftUp;}
之后定义拷贝构造函数,leftUp我采用初始化列表的方式,width  height 在因为未知原因无法用初始化列表,所以我在函数体内定义。

inline Rectangle::Rectangle(const Rectangle& other) : leftUp(new Point(other.leftUp->get_x(), other.leftUp->get_y()))//深度拷贝,需要Point有构造函数{width = other.width;height = other.height;}
测试:

guo::Rectangle r1(1,1,1,1);//构造函数定义法guo::Rectangle r2(2, 2, 1, 1);//构造函数定义法guo::Rectangle r3(r2);//拷贝构造函数定义法guo::Point p1(1, 2);//构造函数定义法//cout << r1.get_height();cout <<"r1="<< r1;cout << "r2=" << r2;cout << "r3=" << r3;
最后定义拷贝赋值函数,分为三步:

1.delete原空间

2.this->leftUp用new定义一个和Point类一样大小的空间并赋值

3.给 width  height  赋值

但是要考虑要拷贝赋值的对象和原对象相同,这样会自我赋值会把自己给delete掉,从而出错。所以专门为这块写一段代码:

if (this == &other)//重复自我赋值{return *this;}
这样拷贝赋值函数就写好了

inline Rectangle& Rectangle::operator=(const Rectangle& other)//拷贝赋值函数{if (this == &other)//重复自我赋值{return *this;}delete this->leftUp;this->leftUp = new Point(other.leftUp->get_x(), other.leftUp->get_y());this->width = other.width;this->height = other.height;return *this;}
测试拷贝赋值函数:

r1 = r3;cout << "r1=r3(拷贝赋值测试)" << endl;cout << "r1=" << r1;//拷贝赋值测试
这样Rectangle类的基本创建功能就定义好了,下周再来实现其他功能,最后放一下所以代码。

//本文件名  Rectangle.h我的编程环境VS2013/*本程序的注释代表仅代表个人理解,不一定完全正确,全是我亲自敲上去的,如有错误请联系我*/#ifndef __RECTANGLE_H__#define __RECTANGLE_H__#include<iostream>namespace guo{class Shape{int no;};class Point{private:int x;int y;public:Point(int x1, int y1) : x(x1), y(y1){  }//构造函数,支持指针类型深度拷贝int get_x() const { return x; }int get_y() const { return y; }};class Rectangle : public Shape{private:int width;int height;Point * leftUp;public:Rectangle(int width1, int height1, int x1, int y1);//构造函数Rectangle(const Rectangle& other);//拷贝构造函数Rectangle& operator=(const Rectangle& other);//拷贝赋值函数~Rectangle();//析构函数 只声明不定义会出无法解析的错误int get_width() const { return width; }int get_height() const { return height; }Point* get_leftUp() const { return leftUp; }};inline Rectangle::Rectangle(int width1, int height1, int x1, int y1) : width(width1), height(height1), leftUp(new Point(x1, y1))//深度拷贝,需要Point有构造函数{;}inline Rectangle::~Rectangle(){delete[] leftUp;}inline Rectangle::Rectangle(const Rectangle& other) : leftUp(new Point(other.leftUp->get_x(), other.leftUp->get_y()))//深度拷贝,需要Point有构造函数{width = other.width;height = other.height;}inline Rectangle& Rectangle::operator=(const Rectangle& other)//拷贝赋值函数{if (this == &other)//重复自我赋值{return *this;}delete this->leftUp;this->leftUp = new Point(other.leftUp->get_x(), other.leftUp->get_y());this->width = other.width;this->height = other.height;return *this;}}#endif


//本文件名  Rectangle.cpp我的编程环境VS2013/*本程序的注释代表仅代表个人理解,不一定完全正确,全是我亲自敲上去的,如有错误请联系我*/#include<iostream>#include"Rectangle.h"#include<Windows.h>//这个头文件中包含类似Rectangle的东西,会使Rectangle无法定义对象using namespace std;//using guo::Point;//using guo::Shape;//using guo::operator<<;ostream& operator<<(ostream& os, guo::Rectangle& str){return os << '(' << str.get_height() << ',' << str.get_width() << ',' << str.get_leftUp()->get_x() << ',' << str.get_leftUp()->get_y() << ')' << endl;}int main(){guo::Rectangle r1(1,1,1,1);//构造函数定义法guo::Rectangle r2(2, 2, 1, 1);//构造函数定义法guo::Rectangle r3(r2);//拷贝构造函数定义法guo::Point p1(1, 2);//构造函数定义法//cout << r1.get_height();cout <<"r1="<< r1;cout << "r2=" << r2;cout << "r3=" << r3;r1 = r3;cout << "r1=r3(拷贝赋值测试)" << endl;cout << "r1=" << r1;//拷贝赋值测试system("pause");//头文件 Windows.h ,因为vs2013不会自动添加增加  mov ah,1  int 21H mov ax,4C00H  int 21H   所以屏幕一闪而过。//getchar();//也可以用这个函数等待输入一个字符来让程序等待,缺点是如果有输入,很容易不好用,所以建议用命名空间解决该问题return 0;}











1 0
原创粉丝点击