1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作。以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时间,static类型记录对象数量,static机制查询相关书籍。
//Time.h #ifndef Time_h #define Time_h class Time { public: Time(int h = 0, int m = 0, int s = 0); void SetTime(int, int, int); void printMilitary( ); //Military style void printStandard( ); //Standard style ~Time(); static int count; private: int hour; //0-23 int minute; //0-59 int second; //0-59 }; #endif // Time_h //Time.cpp #include <iostream> #include "time.h" using namespace std; int Time::count = 0; Time::Time(int h, int m, int s) { count++; hour = h; minute = m; second = s; } //Time Time::~Time() { count--; cout << "~Time is called." << endl; } //~Time void Time::SetTime(int h, int m, int s) { hour = ((h >= 0 && h < 24) ? h : 0); minute = ((m >= 0 && m < 60) ? m : 0); second = ((s >= 0 && s < 60) ? s : 0); } //SetTime void Time::printMilitary() { cout << (hour < 10 ? "0" : "") << hour << ":" << (minute < 10 ? "0" : "") << minute << ":" << (second < 10 ? "0" : "") << second << endl; return; } void Time::printStandard() { cout << ((hour == 0 || hour == 12) ? 12 : hour % 12) << ":" << ((minute < 10) ? "0" : "") << minute << ":" << ((second < 10) ? "0" : "") << second << ((hour < 12) ? "AM" : "PM") << endl; return; } //main.cpp #include "time.h" int main() { Time a(23,23,12); Time b(4, 32, 7); a.printMilitary(); a.printStandard(); b.printMilitary(); b.printStandard(); return 0; }
2nd,构造函数和析构函数,以下代码可以准确示意析构函数调用的时机,觉得不够详细还可以自己继续加入cout语句输出信息。
这个代码的大意就是:class myClass 中还有类型为 classA、classB的数据,它们以初始化列表形式赋值,构造函数调用顺序:ABC,析构函数调用顺序CBA。构造函数分配了内存,析构函数中要记得释放内存。
/*********************************************** Class A Constructor ! x=0 Class B Constructor ! x=0 Class C Constructor ! Class C Destructor ! Class B Destructor ! Class A Destructor ! Class A Constructor ! x=3 Class B Constructor ! x=3 Class C Constructor ! With Initial List Class A Constructor ! x=22 Class B Constructor ! x=65 Class C Constructor ! With Initial List Class C Destructor ! Class B Destructor ! Class A Destructor ! Class C Destructor ! Class B Destructor ! Class A Destructor ! 请按任意键继续. . . ************************************************/ //ClassA.h #if _MSC_VER >1000 #pragma once #endif // class classA { public: classA(int = 0); virtual ~classA(); }; //classA.cpp #include "classA.h" #include <iostream> using namespace std; classA::classA(int x) { cout << "Class A Constructor ! x=" << x << endl; } classA::~classA() { cout << "Class A Destructor !" << endl; } //classB.h #if _MSC_VER >1000 #pragma once #endif // class classB { public: classB(int = 0); virtual ~classB(); }; //classB.cpp #include "classB.h" #include <iostream> using namespace std; classB::classB(int x) { cout << "Class B Constructor ! x=" << x << endl; } classB::~classB() { cout << "Class B Destructor !" << endl; } //myClass.h #include "classA.h" #include "classB.h" #if _MSC_VER >1000 #pragma once #endif // class myClass { public: myClass(int); myClass(); myClass(int, int, int); virtual ~myClass(); private: int year; classA objA; //Constructor Turn:A -> B ->C; classB objB; }; //myClass.cpp #include "myClass.h" #include<iostream> using namespace std; myClass::myClass(int y) { cout << "Class C Constructor !" << endl; year = y; } myClass::myClass():objA(3),objB(3) { cout << "Class C Constructor ! With Initial List" << endl; } myClass::myClass(int y, int a, int b):year(y),objA(a),objB(b) { cout << "Class C Constructor ! With Initial List" << endl; } myClass::~myClass() { cout << "Class C Destructor !" << endl; } //main.cpp #include "myClass.h" #include<iostream> int main() { myClass * pmyobj; pmyobj = new myClass(1900); delete pmyobj; std::cout << std::endl << std::endl; myClass myobj; std::cout << std::endl << std::endl; myClass myobj2(2014, 65, 22); std::cout << std::endl << std::endl; return 0; }
3rd,拷贝构造函数,首先意识到有系统会有默认拷贝构造函数存在,就像有默认的构造函数和析构函数一样。本科时候用VC 6.0编程,拷贝构造函数和operator = 必须要自己定义,尤其是构造函数中有new 的情况。刚刚用了VS2015试了一个程序,发现默认的拷贝构造函数在值类型时传递的是拷贝的值,而对于char * ,则与原对象的值共享,如果析构了原对象,会引发错误(野指针),debug assertion failed,所以还是要自己定义拷贝构造函数。这里谈下浅拷贝和深拷贝。浅拷贝一句话:不涉及内存分配,传递值类型。深拷贝:要分配内存复制值。
这是浅拷贝 - 用默认拷贝构造函数,会有错误的。
//myClass.h #if _MSR_VER > 1000 #pragma once #endif #include <string> class myClass { public: myClass(char * = NULL, int = 1900); void print(); ~myClass(); private: char * name; int year; }; //myClass.cpp #include "myClass.h" #include <iostream> using namespace std; myClass::myClass(char *n, int y) { year = y; name = NULL; if (n) { int len = strlen(n) + 1; name = new char[len]; strcpy_s(name, len, n); } } //myClass myClass::~myClass() { if (name) delete [] name; } //~myClass void myClass::print() { cout << name << "--" << year << endl; } //main.cpp #include "myClass.h" #include<iostream> using namespace std; int main() { int a = 1992, b(a); myClass sd1("ABC", a), sd2("XYZ", b + 1); myClass sd3(sd1); // sd1.print(); sd2.print();
return 0; }
深拷贝代码如下,加入进去就不会有错误。
//myClass.h class myClass { public: myClass(const myClass & a); }; //class myClass //myClass.cpp myClass::myClass(const myClass & a) { year = a.year; name = NULL; if (a.name) { int tmplen = strlen(a.name) + 1; name = new char[tmplen]; strcpy_s(name, tmplen, a.name); } } //main.cpp int a = 1992, b(a); myClass sd1("ABC", a); myClass sd2(sd1); //deep copy! sd1.print(); sd2.print();
深拷贝函数与类名相同,参数类型为对象的引用,看作是特殊的构造函数吧,注意,并不是所有类都要定义拷贝构造函数,例如网络链接中,同时,此时,operator = 也一并禁止掉吧。