C++ 类、构造析构、深拷贝

1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作。以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时间,static类型记录对象数量,static机制查询相关书籍。

//Time.h
#ifndef Time_h
#define Time_h class Time {
public:
Time(int h = , int m = , int s = );
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 = ; 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 >= && h < ) ? h : );
minute = ((m >= && m < ) ? m : );
second = ((s >= && s < ) ? s : );
} //SetTime void Time::printMilitary() { cout << (hour < ? "" : "") << hour << ":"
<< (minute < ? "" : "") << minute << ":"
<< (second < ? "" : "") << second << endl;
return;
} void Time::printStandard() {
cout << ((hour == || hour == ) ? : hour % ) << ":"
<< ((minute < ) ? "" : "") << minute << ":"
<< ((second < ) ? "" : "") << second
<< ((hour < ) ? "AM" : "PM") << endl;
return;
} //main.cpp
#include "time.h" int main() {
Time a(,,);
Time b(, , ); a.printMilitary();
a.printStandard();
b.printMilitary();
b.printStandard(); return ;
}

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 = );
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 = );
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(),objB() {
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(); delete pmyobj; std::cout << std::endl << std::endl; myClass myobj;
std::cout << std::endl << std::endl; myClass myobj2(, , );
std::cout << std::endl << std::endl;
return ;
}

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 = );
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) + ;
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 = , b(a);
myClass sd1("ABC", a), sd2("XYZ", b + ); myClass sd3(sd1); //
sd1.print();
sd2.print(); return ;
}

深拷贝代码如下,加入进去就不会有错误。

//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) + ;
name = new char[tmplen];
strcpy_s(name, tmplen, a.name);
}
} //main.cpp
int a = , b(a);
myClass sd1("ABC", a);
myClass sd2(sd1); //deep copy!
sd1.print();
sd2.print();

深拷贝函数与类名相同,参数类型为对象的引用,看作是特殊的构造函数吧,注意,并不是所有类都要定义拷贝构造函数,例如网络链接中,同时,此时,operator = 也一并禁止掉吧。

上一篇:我对Padding Oracle Attack的分析和思考


下一篇:【HTTP】Fiddler(一) - Fiddler简介