c++特殊函数
C++中NULL不能写作小写,NULL的值为零,也可以写作0
在自己写的复制构造函数中不改变原对象,所以传进来的参数可以设为const类型的,这样可以保证传进来的对象不被改变
比如A(const A &a)
同时注意,如果再函数体中不改变任何变量,那么这个函数也可以设为const,也就是把函数体前(大括号前面)面加上const
编译器提供默认构造函数和析构函数,同时也提供复制构造函数,编译器提供的默认复制构造函数只是把传递进来的对象的每个成员变量复制到新对象的成员变量中去,然后两个对象中的变量均指向存放类成员变量的那块内存区域,假如该变量不是指针变量一般不会出错,假如该变量是指针变量,释放一个对象的内存空间的时候另一个对象会受到影响,因为本来两个对象中的指针指向同一块内存区域,释放其中一个对象的时候,其中的指针变量指向的内存区域也被释放,这时候没被释放的对象中的指针变量成员就成为一个迷途指针,找不到原来指向的那个对象的变量了(这时候需要自己写深层复制构造函数函数,代码在下面)
下面用代码演示默认复制构造函数:
#include <iostream>
using namespace std;
class A
{
public:
A(){x = new int; *x = ;}
~A() {delete x; x = NULL;}
A(const A &a)
{
cout << "复制构造函数执行!\n" << endl;
x = a.x; //其中x是新复制的对象的成员,可以用this.x表示,不加this的时候,系统默认加上
}//我们不写复制构造函数的时候系统自动为我们加上这样一个复制构造函数
void print()const{cout << *x << endl;}
void set(int i){*x = i;}
private:
int *x;
};
int main()
{
A *a = new A;
a->print();
A b = (*a);
b.print();
a->set();
b.print();
delete a;
b.print();
return ;
}
假设自己写构造函数就不会出现浅层复制造成的错误:(上述代码改为深层复制后代码如下)
#include <iostream>
using namespace std;
class A
{
public:
A(){x = new int; *x = ;}
~A() {delete x; x = NULL;}
A(const A &a)
{
cout << "复制构造函数执行!\n" << endl;
x = new int;
*x = *(a.x);
}
int get()const{return *x;}
void set(int i){*x = i;}
private:
int *x;
};
int main()
{
A *a = new A;
cout << "*(a.x):" << a->get() << endl;
A b = (*a);
cout << "*(b.x):" << b.get() << endl;
a->set();
cout << "*(a.x):" << a->get() << endl;
cout << "*(b.x):" << b.get() << endl;
delete a;
cout << "删除a之后*(b.x):" << b.get() << endl;
return ;
}
复制构造函数会完成两个对象之间的拷贝
隐式转换有时候会造成一些错误,需要关闭隐式转换的话可以在构造对象的时候加上关键词explicit,不加explicit的话默认可以进行隐式转换
我们可以把数字当作对象赋给另一个对象,这样在对该赋值表达式进行计算的时候,首先要对数字进行类型转换,同时判断该类的构造函数的参数是否与数字的类型匹配,假如匹配则调用 构造函数创建一个临时对象,跟着将该临时对象赋给复制操作左边的对象,最后调用析构函数删除临时对象(判断匹配然后转换的过程叫做隐式转换)
#include <iostream>
using namespace std;
class A
{
public:
explicit A(int x){i = x; cout << "构造函数执行!" << endl;}
~A() {cout << "析构函数执行!\n";}
void get() {cout << i << endl;}
private:
int i;
};
int main()
{
A a();
a.get();
a = A(); //这里也可以写成a = 1000;这样的话该对象的构造函数前面不能加explicit,
return ; //因为加上explicit之后,该对象就不能进行隐式类型转换了
}
delete会调用析构函数删除在堆中创建的空间
#include <iostream>
using namespace std;
//本代码演示了delete 会调用析构函数来释放new运算符创建的内存空间
//本代码还演示了在堆中创建对象
//注意在堆中创建的对象必须手动删除,本代码没有删除第二个对象
class A
{
public:
A(){cout << "构造函数执行!" << endl;}
~A(){cout << "析构函数执行!\n";}
void set(int a, char b)
{
i = a;
j = b;
}
void print()
{
cout << i << " " << j << endl;
}
private:
int i;
char j;
};
int main()
{
A *a;
a = new A; //在堆中创建对象
a->set(, 'a');
a->print();
delete a;
cout << endl << endl;
A *b = new A;
b->set(, );
return ;
}
复制构造函数:(注:如果不写复制构造函数的话系统自动加上默认复制构造函数)
#include <iostream>
using namespace std;
class A
{
public:
A(){}
A(A&one){n = one.n; m = one.m;} //默认构造函数就是这样写的,假设我们不写,系统自动加上
A(int i, int j){n = i; m = j;}
void print()
{
cout << "n: " << n << " m: " << m << endl;
}
private:
int n, m;
};
int main()
{
A a(, );
a.print();
A b(a); //这时候a的值就传给b了
b.print();
return ;
}
函数声明的时候可以只写参数类型,不写参数名
当函数的参数缺省的时候,如果给函数传递参数,则函数的参数为传进来的数,否则
函数的参数为默认值
函数参数缺省和函数重载的使用有几分相像,但是不同:
具有默认参数的函数重载的是参数的数值,而重载函数重载的是参数的类型。
1:普通函数参数的缺省
#include <iostream>
using namespace std;
void fun(int n = , int m = )
{
cout << "n:" << n << " m:" << m << endl;
} int main()
{
fun(); //输出默认参数0 0
fun(,);//输出参数1, 2
return ;
}
2:类中方法的参数缺省
#include <iostream>
using namespace std;
class A
{
public:
void set(int = , int = );
void count(bool = false);
private:
int w;
int h;
};
void A::set(int width, int height)
{
w = width;
h = height;
}
void A::count(bool val)
{
if(val)
cout << "val的值为真时:" << w*h << endl;
else
cout << "val的值为假时:" << w*h/ << endl;
}
int main()
{
A a;
a.set();
a.count();
a.count(true);
a.set(,);
a.count();
a.count(true);
return ;
}
不仅普通函数可以重载,构造函数也可以重载:
/*构造函数也可以重载*/
#include <iostream>
using namespace std;
class rectangle
{
public:
rectangle(){cout << "构建一个长方形\n";}
rectangle(int l, int w){ length = l; width = w; cout << "长方形的面积为:" << length*width << endl;}
rectangle(int l, int w, int h){length = l; width = w; height = h; cout << "长方体的体积为:" << l*w*h << endl;}
private:
int length;
int width;
int height;
};
int main()
{
rectangle();
rectangle(, );
rectangle(, , );
return ;
}
对成员变量初始化的另一种方式
在函数体前面也就是函数名后面加冒号同时加上变量和对应的初始化值,
这种方法是对成员变量的初始化,而不是赋值
/*可以在构造函数头对常量和引用初始化;这种方法和在函数中对变量赋值都是给成员变量一个值,但是有所不同
1:在函数头实际上是初始化
2:在函数中的语句实际是赋值语句
区分赋值语句和初始化语句
初始化:即定义的时候进行赋值 比如说你定义的某个对象的成员是常量,那么在该对象的方法体中对该常量赋值会报错
但是在函数头对该常量赋值就会正常运行
由此我们可以看出在函数头和在函数中给一个变量赋值的区别
在函数头的实际是初始化语句,在函数中对对象的成员赋值才是赋值语句*/ #include <iostream>
using namespace std;
class rectangle
{
public:
rectangle():length(), width(){cout << "长方形的面积为:"<< length * width;}
private: //在函数名字后面加上冒号,然后是给每个变量赋的值,如果有多个赋值语句,中间用逗号隔开
const int length; //因为在函数名字后面加冒号写上给他们的值得话相当于对成员变量初始化,所以不会报错
int width; //如果直接在函数体中对常量赋值会报错,因为不能对常量赋值,只能对常量初始化
};
int main()
{
rectangle();
return ;
}
构造函数的初始化顺序:
它是按照定义时候的成员列表中的初始化顺序来的,析构的时候是先析构最后构造的那个成员
#include <iostream>
using namespace std;
/*构造函数的初始化顺序,它是按照成员列表的初始化顺序来的,并不看你在构造函数中先对谁赋值 然而析构函数是首先析构成员列表中最后构造的函数*/
class demo
{
public:
demo(){x = ; cout << "demo的默认构造函数" << endl;}
demo(int i){x = i; cout << "demo的带一个参数的构造函数" << x << endl;}
~demo(){cout << "demo的默认析构函数" << endl;}
int get(){return x;}
void set(int i) {x = i;}
private:
int x;
};
class rectangle
{
public:
rectangle(){x = ; cout << "rectangle的默认构造函数" << endl;};
rectangle(int i, int j, int k):x(i), width(j), length(k)
{
cout << "rectangle的带三个参数的构造函数!" << "长方形的面积为:" << length.get()*width.get() << endl;
}
~rectangle(){cout << "rectangle的默认析构函数" << x << endl;}
private:
int x;
demo width;
demo length;
};
int main()
{
rectangle a(, , );
return ;
}
再强调下常量和引用必须初始化,如果是类中的对象的话,需要按照在函数体前面赋值的方法初始化
#include <iostream>
class A
{
public:
A(int a, int b):num(a),total(b)
{
/*
下面的写法不对,因为常量和引用只能初始化不能赋值
num = a;
total = b;
*/
}
private:
const int num;
int &total;
};
int main()
{
A a(, );
return ;
}
c++特殊函数的更多相关文章
- Qt Creator+MinGW+boost特殊函数的使用示例
Qt Creator+MinGW+boost特殊函数的使用示例: 先编译和安装boost: bootstrap.bat gcc .\b2 --toolset=gcc --prefix=E:\boost ...
- 数字信号处理专题(2)——利用FPGA进行基本运算及特殊函数定点运算
一.前言 FPGA以擅长高速并行数据处理而闻名,从有线/无线通信到图像处理中各种DSP算法,再到现今火爆的AI应用,都离不开卷积.滤波.变换等基本的数学运算.但由于FPGA的硬件结构和开发特性使得其对 ...
- Day10 Python基础之特殊函数(八)
一些特殊函数 1.递归函数(recursion) 递归函数的定义:在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归函数的优点:是定义简单,逻辑清晰.理论上,所 ...
- Kotlin入门(11)江湖绝技之特殊函数
上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...
- 以太坊系列之十四: solidity特殊函数
solidity中的特殊函数 括号里面有类型和名字的是参数,只有类型是返回值. block.blockhash(uint blockNumber) returns (bytes32): hash of ...
- python特殊函数
__doc__ 类(实例).__doc__ 类的描述信息 '''class des''' __module__ 类(实例).__module__ 表示当前操作的对象在那个模块 __class__ ...
- 08.C语言:特殊函数
C语言:特殊函数 1.递归函数: 与普通函数比较,执行过程不同,该函数内部调用它自己,它的执行必须要经过两个阶段:递推阶段,回归阶段: 当不满足回归条件,不再递推: #include <stdi ...
- Js基础知识(作用域、特殊函数---自调、回调、作为值的函数)
15.作用域 概念: 规定变量或函数的可被访问的范围和生命周期 分类: 全局作用域 -就是指当前整个页面环境: 局部作用域(函数作用域) -就是指某个函数内部环境 l 变量的作用域 全局变量 - 定义 ...
- 常见PHP危险函数及特殊函数
PHP代码执行函数 - eval & assert & preg_replace mixed eval ( string $code ) 把字符串 $code 作为PHP代码执行. 很 ...
- SciPy 特殊函数
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
随机推荐
- 【Java】 实现一个简单文件浏览器(2)
接着上篇文章 接下来说下程序右侧的文件内容表格如何实现 FileTable类: FileTable基础于JTable类,构造函数里用setDefaultRenderer设置每行默认的渲染器为FileT ...
- PHP输出中文乱码的解决方法
最近在windows上发现PHP程序中输出来的中文有乱码的情况. 看了很多帖子资料说可以在页面上添加: http://www.cnblogs.com/leandro/archive/2008/04/2 ...
- 理解Ajax
1.优化原则 优化的目的是希望降低程序的整体开销.虽然在程序中有许多因素可以优化,但是通常人们会认为这个开销就是程序的执行时间.其实我们更应该把重点放在对程序整体开销最大的那部分. 2.一切都是权 ...
- divmod数字处理函数
divmod(a,b)函数 中文说明: divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数 返回结果类型为tuple 参数: a,b可以为数字(包括复数) 版本: 在python2 ...
- [转]swift 学习资源 大集合
今天看到了一个swift的学习网站,里面收集了很多学习资源 [转自http://blog.csdn.net/sqc3375177/article/details/29206779] Swift 介绍 ...
- strlen源码剖析
学习高效编程的有效途径之一就是阅读高手写的源代码,CRT(C/C++ Runtime Library)作为底层的函数库,实现必然高效.恰好手中就有glibc和VC的CRT源代码,于是挑了一个相对简 ...
- 【双模卡的相关知识】解SIM卡前需要知道的信息(SIM年分和厂商识别)
<ignore_js_op> 二.SIM版本问题SIM卡的版本有两种说法,一是有些是制造厂制定的,二是电信公司的制定.下面以移动为例,目前我们手里的SIM有几种版本:v0.v1.v2.v3 ...
- Flex 动画效果
1.使用自带效果 在Flex里面不像在Flash里面随意制作动画了,Flex更趋向于应用程序,而不是动画制作了,所以没有了时间轴的概念.在Flex中使用动画效果,可以用Flex自带的Effect,或者 ...
- Qt Creator needs a compiler set up to build. Configure a compiler in the kit options - Stack Overflow
Qt Creator needs a compiler set up to build. Configure a compiler in the kit options - Stack Overflo ...
- java面试题系列11
华为的JAVA面试题 QUESTION NO: 1 publicclass Test1 { publicstaticvoid changeStr(String str){ ...