感觉现在的面试都很有意思,上来就问你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;
}