种设计的几点认识及设计一个自己的类String类
感觉现在的面试都很有意思,上来就问你C++中虚函数表 ,你了解吗,是怎么实现的?对最基本的类设计从来不问。甚至问你用C实现C++的多态。
其实,能否设计一个基本类,能体现对C++的类设计的掌握情况。(今年,中兴,和东软的笔试题中好像都有设计类的题, 但是也不能防止某些人背过)。
个人认为,一个好的类设计,应该是使类类型像我们熟知的基本类型一样使用,即使类像基本类型一样使用。
不考虑继承,不考虑多态,设计的类类型应该考虑一下几个方面:
1. 无参数的构造函数(default constructor): 当类无任何构造函数,编译器自动生成一个构造函数。
但是,当声明其他参数的构造函数,编译器将不能生成default constructor。随之,而来的问题,你不能像基本类型那样声明变量;也不能声明该类类型的数组。
2. 拷贝构造函数( copy constructor):用一个对象初始化另一个对象。(仅此情形,无论函数参数的值传递,还是 return 值传递,都是此情形)。
初始化,则意味着另一个对象从未调用过构造函数,只是分配了内存。
3. 赋值操作符(assignment operator =): 对已初始化的对象的赋值。已初始化的对象即曾用调用过构造函数。
4. 析构函数(destructor): 析构函数,当对象过期(out of scope)时,对对象进行析构操作(防止内存泄露,或者资源泄露)。
显式地调用析构函数 并未释放该类对象所占的内存,类对象的内存释放,是类的存储管理的一部分。
对于支持多态的基类,其析构函数一定要为virtual,(尽管派生类的类名 不与基类的类名一样,但其可构成协变重写)。
5.delete/new(类的存储管理):首先要搞清楚几个概念:new operator与operator new的区别以及delete operator与 operator delete的区别。
new operator:平时 new 一个对象的这个new就是new operator:其背后做哪些工作呢?
<1>调用operator new(这个是标准存储分配库函数,也可以在类设计时对其重写),分配该类对象的内存空间。
<2> 调用该类的构造函数, 完成类对象的初始化.(包括动态内存的分配,资源的分配等)。
delete operator:同理 delete operator也在默默做着一些工作:
<1> 调用类的析构,函数完成类对象的去初始化,即(动态分配内存、资源的回收)防止内存、资源泄露。
<2> 调用 operator delete 回收该类对象的内存。
此外,对数组的内存的分配与回收的:operator array new 和operator array delete;
对于不考虑类继承的String类的设计:如下:
1. 类的声明文件:MyString.h
#ifndef __MyString_h #define __MyString_h #include <iostream> #include <cstring> using namespace std; class MyString{ char *str; public: MyString(); //default constructor; ~MyString(); //default destructor; MyString(const MyString & that); // copy constructor MyString& operator=(const MyString &that); //assignment operator MyString(const char *str); //转换 constructor void print() { cout << str << endl; cout << endl; } }; #endif
2.类的实现文件: MyString.cpp
#include "MyString.h" //default constructor MyString:: MyString() : str(NULL) { cout << "Constructor: MyString()" << endl; str = new char[1]; str[0] = '\0'; } //转换构造函数 MyString::MyString(const char *str) { cout << "Constructor: MyString(const char *)" << endl; if(NULL == str) { this->str = new char[1]; this->str[0] = '\0'; }else { this->str = new char[strlen(str) + 1]; strcpy(this->str, str); } } //copy constructor MyString::MyString(const MyString &that) { cout << "Copy Constructor Mystring(const Mystring &that) " << endl; str = new char[strlen(that.str) + 1]; strcpy(str, that.str); } // assignment operator = MyString& MyString::operator=(const MyString &that) { cout << "assignment operator: operator=(const MyString &that)" << endl; if(this != &that) { char *tmp = new char[strlen(that.str) + 1]; strcpy(tmp, that.str); delete [] str; str = tmp; } return *this; } MyString::~MyString() { cout << "Destructor: ~MyString()" << endl; if(str) { delete[] str; str = NULL; } }
3.测试文件:main.cpp
#include "MyString.h" int main() { MyString s; //default constructor s.print(); MyString ss("hello"); //转换构造函数 constructor ss.print(); MyString sss = ss; // copy constructor 用一个对象初始另一个对象 sss.print(); MyString ssss(s); // copy constructor; ssss = sss; //assignment operator = : 给一个已初始化的对象赋值 ssss.print(); MyString sssss = "hello world"; // wrong, as explicit modified. sssss.print(); return 0; }
另一个类实现:Clock
#include <iostream> using namespace std; class Clock { public: Clock(int hour, int minute, int second); Clock(const Clock &that); //复制构造函数 Clock &operator=(const Clock &that); ~Clock(); //析构函数 void SetTime(int hour, int minute, int second); void ShowTime(); private: int _hour; int _minute; int _second; }; Clock::Clock(int hour, int minute, int second): _hour(hour), _minute(minute), _second(second) { cout << "constructor Clock(int, int, int)" << endl; } Clock::Clock(const Clock &c) { //复制构造函数 cout << "copy constructor" << endl; SetTime(c._hour, c._minute, c._second); } Clock &Clock::operator=(const Clock &that) { cout << "in operator=(Clock &that) " << endl; if(this != &that) { //防止自我赋值 //this->~Clock(); SetTime(that._hour, that._minute, that._second); } return *this; } void Clock::SetTime(int hour, int minute, int second) { _hour = hour; _minute = minute; _second = second; } void Clock::ShowTime() { cout << _hour << ":" << _minute << ":" << _second << endl; } Clock::~Clock() { cout << "destructor: ~Clock()" << endl << endl; } Clock GetClock(); int main() { Clock GetClock(); //声明函数 Clock myClock1(1, 2, 3); //构造函数 Clock(int, int, int) myClock1.ShowTime(); cout << endl << endl; Clock myClock2(myClock1); // copy constructor Clock(const Clock &c); myClock2.ShowTime(); cout << endl << endl; Clock myClock3 = GetClock(); //copy constructor Clock(const Clock &c); 可能被优化。 myClock3.ShowTime(); cout << endl << endl; myClock3 = myClock2; // assignment operator=(const Clock &that); myClock3.ShowTime(); cout << endl << endl; myClock3 = GetClock(); //copy constructor && operator= () 。 myClock3.ShowTime(); cout << endl << endl; } Clock GetClock() { cout << "in Fuction: GetClock()" << endl; Clock tmpClock(5,6,7); //构造函数 Clock(int, int, int) return tmpClock; }