这里写一个钟表类,读者可以通过复制整个代码到vs中运行试验,从这个例子中体会一个类的基本写法,下一篇博客讲解继承,在观察这个例子的时候,注意以下几点:
1,关注类的简单语法
2,关注类的成员变量一般私有
3,关注类的构造函数的一般写法与调用
4,关注析构函数的使用,析构函数只有一个,如果类中有动态申请的内存资源(堆资源),一定要在析构函数中释放。
5,关注拷贝构造函数的使用,深拷贝与浅拷贝;默认的拷贝构造函数为浅拷贝,被复制对象中如果有堆资源时,两者共用该堆资源。这种情况下两个对象析构时会调用两次析构函数,即对同一片堆内存释放两次,程序奔溃。因此如果类中有堆资源时,要重写拷贝构造函数,新对象也申请属于自己的堆资源。
6,关注类对象的创建方法——分为栈对象和堆对象,详情见代码。
#define _CRT_SECURE_NO_WARNINGS #includeusing namespace std; class CClock { private://private表示只能类内访问 char* m_From; int m_Hour; int m_Minute; int m_Second; public://表示类内与类外都都可访问,还有protect权限与继承有关,在后面的博客 CClock();//此处重写了构造函数中的默认构造函数,如果后面直接写=default表示使用默认的构造函数,自己不用写;如果是=delete表示不使用该构造函数 CClock(int a);//含有一个参数的构造函数,该函数既表示构造函数,又表示一种隐式转换,从而还可以这样调用CClock obj=1; CClock(int n, int k);//看看实现当中如何用参数列表书写构造函数 CClock(int a, int b, int c);//含有三个参数的构造函数 CClock(char* s, int a, int b, int c);//看该构造函数的实现,里面有动态申请的内存,所以要特别注意析构函数要注意释放。 CClock(CClock& obj);//重写拷贝构造函数为深拷贝 void getTime(); void setClock(char* s,int a,int b,int c); ~CClock(); }; CClock::CClock(){ cout << "调用了CClock()构造函数" << endl; m_From = nullptr; } CClock::CClock(int a) { cout << "调用了CClock(int a)构造函数" << endl; m_Hour = a; m_From = nullptr; } CClock::CClock(int n, int k) : m_Hour(n), m_Minute(k) { cout << "调用了CClock(int n, int k)构造函数" << endl; m_From = nullptr; } CClock::CClock(int a, int b, int c) { cout << "调用了CClock(int a, int b, int c)构造函数" << endl; if ((a < 0 || a >= 24) || (b < 0 || b >= 60) || (c < 0 || c >= 60)) return; else { m_Hour = a; m_Minute = b; m_Second = c; m_From = nullptr; } } CClock::CClock(char* s, int a, int b, int c) { cout << "调用了CClock(char* s, int a, int b, int c)构造函数" << endl; m_From = new char[255];//类内部动态申请了堆资源,析构函数中注意释放 strcpy(m_From, s); m_Hour = a; m_Minute = b; m_Second = c; } CClock::CClock(CClock& obj) { cout << "调用了CClock(CClock& obj)拷贝构造函数" << endl; m_From= new char[255]; strcpy(m_From, obj.m_From); m_Hour = obj.m_Hour; m_Minute = obj.m_Minute; m_Second = obj.m_Second; } CClock::~CClock() { if (m_From != nullptr) { delete[] m_From; cout << "析构并释放堆资源" << endl; } else { cout << "析构" << endl; } } void CClock::getTime()//成员函数getTime()的实现 { if(m_From!=nullptr) cout <<"该表产自于"< ("上海"), 0,0,0);//调用CClock(char* s, int a, int b, int c);构造函数,该构造函数内部申请了堆资源,因此要特别注意析构函数的书写 CClock watche5(watche4); watche4.getTime(); watche5.getTime(); watche0.getTime(); //栈对象在声明的时候自动构造,在出块作用域以后自动析构 CClock* Pwatch0 = new CClock; CClock* Pwatche1 = new CClock(1); CClock* Pwatche2 = new CClock(1, 2);//调用(int n, int k);构造函数 CClock* Pwatche3 = new CClock(1, 2, 3);//调用CClock(int a, int b, int c);构造函数 CClock* Pwatche4 = new CClock(const_cast ("上海"), 0, 0, 0);//调用CClock(char* s, int a, int b, int c);构造函数,该构造函数内部申请了堆资源,因此要特别注意析构函数的书写 Pwatche4->getTime(); delete Pwatch0; delete Pwatche1; delete Pwatche2; delete Pwatche3; delete Pwatche4;//new与delete要搭配使用,new会调用构造函数,delete会调用析构函数,注意不是自动调用析构,而是通过delete调用 CClock* P = new CClock[10]; delete[] P; CClock** PP=new CClock*[10]; for (int i = 0; i < 10; i++) PP[i] = new CClock(1);//创建堆对象数组 for (int i = 0; i < 10; i++) delete PP[i];//释放堆对象数组 delete[] PP; }
需要注意的是:
一,同一个类的对象,其成员函数地址是一样的,表示同一个类的对象的成员函数是共用的,即:
(1)数据是独立的。
(2)成员的函数是共用的.
成员函数调用时会愉愉的传递this指针(this指针指向本对象),通过寄存器ecx传递,这种传递方式称之为thiscall,这的话虽然类的每个对象都用的是同一个函数,但是却会分别 *** 作自己的对象,例如上例中的sh1.setHour(1)与sh2.setHour(2),他们调用的都是同一个函数,甚至函数地址都是一样的,但在调用过程中偷偷传递了this指针,最后分别更改了sh1对象与sh2对象的m_Hour。
二,程序中只提到栈上的局部对象在声明该对象时构造,在出其块作用域时自动析构。没有提到全局对象在进入main函数之前构造,在出main函数之后析构。
三,使用new和delete时注意,new和delete搭配,new []和delete[]要搭配使用。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)