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. 解决 java 使用ssl过程中出现"PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"

    今天,封装HttpClient使用ssl时报一下错误: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExc ...

  2. ArcGIS影像配准与空间配准

    ArcGIS影像配准与空间配准 ArcGIS影像配准与空间配准 地图配准可分为影像配准和空间配准.影像配准的对象是raster图,譬如TIFF图.配准后的图可以保存为ESRI GRID, TIFF,或 ...

  3. Linux 的文本处理命令一览

    grep 基于关键字搜索文本内容 -i 搜索时忽略大小写-n 显示结果所在行数-v 输出不带关键字的行-Ax 在输出的时候包含结果所在行之后的指定行数(x为一个数值,表示输出后面x行)-Bx 在输出的 ...

  4. 无法删除对象 '产品',因为该对象正由一个 FOREIGN KEY 约束引用。

    在删除northwindcs表时,发生报错,消息 3726,级别 16,状态 1,第 2 行,无法删除对象 '产品',因为该对象正由一个 FOREIGN KEY 约束引用.此时判断是因为有其他表的外键 ...

  5. contiki-rime-单跳单播

    rucb是单跳单播的最顶层,将数据以块为单位进行传输(Bulk transfer). ruc,Reliable communication,保证可靠通信,主要实现确认和序列功能. suc,Stubbo ...

  6. malloc error:初始值设定元素不是常量

    #include <stdio.h> #include <stdlib.h> char *buf = (char *)malloc(BUFSIZ); setbuf(stdout ...

  7. String or binary data would be truncated 解决办法

    原因: 一般出现这个问题是因为数据库中的某个字段的长度小,而插入数据大 解决: 找到相应字段,修改表结构,使表字段大小相同或大于要插入的数据

  8. c++11的右值引用、移动语义

    对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂.最近翻翻资料感觉突然开窍,因此记下.其实搞懂之后就会发现这个概念很简单,并无什么高深的地方. 先说说右值引用.右值一般指的是 ...

  9. [HTML/HTML5]6 使用图像

    6.1  将图像作为Web页面的前景元素 使用img元素,就可以在Web页面中添加图像.img是image的缩写.只需在img元素中添加src(source的缩写)属性,并为该属性设置相应的值,就可以 ...

  10. ajax和sap以及网络安全

    1.sap(single page  applaction)一个页面通过众多ajax请求完成的一个app 优点是:减少页面跳转,UI公用部分的重复加载 缺点: 1.ajax过多的请求,对服务器性能有所 ...