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 = 也一并禁止掉吧。

C++ 类、构造析构、深拷贝的更多相关文章

  1. C++类构造析构调用顺序训练(复习专用)

    //对象做函数参数 //1 研究拷贝构造 //2 研究构造函数,析构函数的调用顺序 //总结 构造和析构的调用顺序 #include "iostream" using namesp ...

  2. Effective C++ ——构造/析构/赋值运算符

    条款五:了解C++默认编写并调用那些函数 是否存在空的类? 假设定义类为class Empty{}:当C++编译器处理过后会变成如下的形式: class Empty{ Empty(){} ~Empty ...

  3. EffectiveC++ 第2章 构造/析构/赋值运算

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...

  4. Effective C++ —— 构造/析构/赋值运算(二)

    条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...

  5. 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  6. 《Effective C++》读书笔记 被你忽略的关于构造析构赋值

    如果程序员没有定义,那么编译器会默认隐式为你创建一个copy构造函数,一个copy赋值操作符,一个析构函数.另外如果你没有声明任何构造函数,编译器会为你声明一个default构造函数. 但是只有当这些 ...

  7. HexoC++第04课 构造析构.md

    C++第04课 构造析构.mdhtml {overflow-x: initial !important;}#write, body { height: auto; } #write, #write h ...

  8. C++ map.insert 传参类型不同,构造/析构次数不同

    1. 传参方式 使用 insert 为 map 插值时,insert 的传参包含以下几种可能: make_pair 生成对象 pair(key_type, value_type) 生成对象 pair( ...

  9. c++构造析构顺序

    class A { public: A(){ cout << "constrcut A" << endl; }; ~A(){ cout << & ...

  10. python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用) import HTMLPar ...

随机推荐

  1. Download Free Oracle Reports Building Guide eBook

    A very nice ebook on building reports in Oracle fusion middleware 11g. This manual is intended for a ...

  2. Entity Framework 数据库初始化四种策略

    策略一:数据库不存在时重新创建数据库 Database.SetInitializer<testContext>(new CreateDatabaseIfNotExists<testC ...

  3. Google开源SLAM软件cartographer中使用的UKF滤波器解析

    在Google开源SLAM软件cartographer中,相对<SLAM for dummies>使用了更为复杂.性能更好的Scan匹配与UKF算法,这里简单介绍下cartographer ...

  4. 基于EasyUI的Web应用程序及过去一年的总结

    前言 在这家公司服务了一年时间,一个多月之前已经提交了离职申请,好在领导都已经批准了,过几天就办理手续了,在此感谢领导的栽培与挽留,感谢各位同事在工作中的给我的帮助,感谢师傅(在我心中当他是我师傅,跟 ...

  5. javascript字符转直接量和转义字符

    直接量: 你可以用单引号或者双引号来表示字符串的直接量.但是js的字符串必须是Unicode 字符序列. 转义字符: 主要用在字符串中,包涵控制字符,以及当前操作系统余元所不允许直接输入的字符. 转义 ...

  6. hdu-5525 Product(费马小定理)

    题目来源:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=644&pid=1003 前面用奇偶性约掉2, ...

  7. 专为控制打印设计的CSS样式

    大多数Web设计师对打印控制还不是很熟悉,他们往往更迷恋像素,而不是打印机.在现实世界中,很多人依赖从网站上打印网页来参考: 在这个数字时代, 在一些特殊的场合,很多人手中还会拿着纸张.Web开发人员 ...

  8. Mac 使用技巧

    1.快捷键(Mac 键盘快捷键https://support.apple.com/zh-cn/HT201236) Command-Shift-Z:重做,也就是撤销(Command-Z)的逆向操作 Co ...

  9. 從 Internet 安裝 Cygwin

    從 Internet 安裝 Cygwin 如果您有高速的 Internet 連線, 可以考慮用這個方法, 否則不建議使用 執行 setup.exe Cygwin Setup 畫面, 按 Next. C ...

  10. JQuery_DOM 节点操作之创建节点、插入节点

    一.创建节点 为了使页面更加智能化,有时我们想动态的在html 结构页面添加一个元素标签,那么在插入之前首先要做的动作就是:创建节点 <script type="text/javasc ...