- 浏览: 317747 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
huangyunbin:
swc.advance(); 这个什么时候被调用是最核心的 ...
滑动窗口计数java实现 -
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB 从入门到精通专题教程 -
rryymmoK:
深入浅出MongoDB应用实战开发下载地址:http://pa ...
MongoDB 从入门到精通专题教程 -
u012352249:
怎么支持多个窗口啊?
滑动窗口计数java实现 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB 从入门到精通专题教程
拷贝构造函数与运算符的重载
* 多态
- 前堤:继承,虚函数,指针或引用
- 类型转换 : dynamic_cast 把父类*转换成子类*
- 纯虚函数 : 保证此函数一定不会被执行,抽象类,不能创建对象.
* 友元
- 内部授权,不是成员,这一点很重要,因此也没有this,与之相关的一切
也没有.
- 打破封装,必须有一个类的内部声明,可访问任何成员通过 对象.来访
问.
* 静态
- 是成员
- 大家共用一份成员,整个类共用的成员.
- 静态数据成员: 在外部初始化
- 静态函数只能访问静态成员,类名::成员
====================================================
* 运算符重载(c++特有功能)
* 内部类
* 异常
拷贝构造函数除了名字特殊外毫无特殊之处.如下
当类无构造函数时,会自动产生A(),A(const A&)构造函数.
+ 当类成员有指针成员指向动态内存时默认拷贝构造函数会出问题.
因为它会使两个指针指向同一个地方导致混乱.
这时我们需要重写这个拷贝构造函数.如下示例:
在类的成员函数中可以访问本类中任何成员变量.
自已定义拷贝构造函数之后,就没有默认的拷贝构造函数了,要在
自己定义的拷贝构造函数中处理所有需要处理的数据.
========================================
默认的拷贝构造函数是浅拷贝,自己写的拷贝构造函数是深拷贝.
* 运算符函数
* 单目运算符
运算符重载就是自已写运算符函数来规定运算符如何工作.
--------------------------
运算符函数的实现方法:
* 友元运算符函数:
- 在类中声明friend
- 定义:返回类型 operatorX(形参1,形参2)
- 调用: obj1 X obj2 解释成 operatorX(obj1,obj2),返回值作为运
算结果
* 成员函数: 直接在类中定义
- 定义: 返回类型 operatorX(形参1)
- 调用: obj1 X obj2 解释成 obj1.operator(obj2),返回值作为运算
结果
cout << f1 << f2;//用重载运算符表示,只能通过友员来实现
// 如果要用成员函数,则会有cout.operator<<(const F& f),所以这是不
// 可能的.因此只能用友员来实现,operator<<(cout,f)
// 而cout是ostream型的,因此有以下标准格式.注意不能加const,因为//
cout是要改变的,会改变里的缓冲成员.
ostream& operator<<( /* 不能加const */ ostream& cout, const
F&) //输出运算符的标准重载格式.
friend istream& operator>>(istream& is, F& f){
}//输入运算符重载标准格式
* 单目运算符重载
-友元函数形式,返回类型 operatorX(形参)
使用:X obj ---> operatorX(obj);
-成员函数形式 尽量用成员 返回类型 operatorX(/*无形参*/)
使用: X obj ---> obj.operator();
运算符重载提供了一个自己规定运算符式作方式的方法,至少有一个操
作数是自定义类型的.基本类型我们是规定不了的.
强制类型转换:类型(数据) --> (不必写返回类型,因为始终与后面的类
型是相同的) operator类型(无形参) 只能写成成员函数,不能是友员.
对自定义类型的对象,使用运算符时,总是调用相应的运算符函数
三目运算符不能重载.
等号是双目运算符也可重载,它也只能是成员.
还有点号('.')不能重载.
双冒号(::)不能重载.
sizeof(类型)没法重载.
#号不是运算符,无所谓重载.
'= () [] -> 类型转换'只能是成员函数来重载,其它的随便,我们建议尽量
使用成员函数来写,有点只能用友元,比如输入输出.
==================================================
+ 双目运算符重载
- 友元形式:返 operator符号(形1,形2)
- 成员形式:返 operator符号(形)
+ 单目运算符重载
- 友元: 返 operator符号(形参)
- 成员: 返 operator符号()
+ 特例
- 加加
- 先加加
- 后加加 返回 operator符号(形,int)
- 减减
- 先减减
- 后减减
- 类型转换 只能是成员perator 空格 类型();
* 多态
- 前堤:继承,虚函数,指针或引用
- 类型转换 : dynamic_cast 把父类*转换成子类*
- 纯虚函数 : 保证此函数一定不会被执行,抽象类,不能创建对象.
* 友元
- 内部授权,不是成员,这一点很重要,因此也没有this,与之相关的一切
也没有.
- 打破封装,必须有一个类的内部声明,可访问任何成员通过 对象.来访
问.
* 静态
- 是成员
- 大家共用一份成员,整个类共用的成员.
- 静态数据成员: 在外部初始化
- 静态函数只能访问静态成员,类名::成员
====================================================
* 运算符重载(c++特有功能)
* 内部类
* 异常
拷贝构造函数除了名字特殊外毫无特殊之处.如下
A(const A& obj){ cout << "我是拷贝构造函数" << endl; } A a = obj// 与 A a(obj)是等价的
#include <iostream> using namespace std; class A { int data; public : A():data(5){ //初始化列表初始化的是成员而不是形参 cout << "A()" << endl; } A(int d):data(d){ cout << "A(int)" << endl; } A(bool b):data(b?123:234){ cout << "A(bool)" << endl; } A(char c) : data((int)c){ cout << "A(char)" << endl; } A(const A& o) : data(o.data){ cout << "A(const A&)" << endl; } void show(){ cout << "data=" << data << endl; } virtual ~A(){ cout << "~A()" << endl; } }; int main() { A a1;//调用无参构造函数 A a2(28); A a3(true); A a4('S'); A a5(a2); } //用引用的好处 #include <iostream> using namespace std; class A { int data; public : A():data(5){ //初始化列表初始化的是成员而不是形参 cout << "A()" << endl; } A(int d):data(d){ cout << "A(int)" << endl; } A(bool b):data(b?123:234){ cout << "A(bool)" << endl; } A(char c) : data((int)c){ cout << "A(char)" << endl; } //A(const A& o) : data(o.data){ // cout << "A(const A&)" << endl; //} //形参是一个新变量,在调用时创建,由实参来初始化. A(A o) : data(o.data){ //这样写是错误的,进入死循环 cout << "A(const A&)" << endl; } //创建对象时要调构造函数,调构造函数创建形参,形参又是一个新对象, //创建新对象又要调构造函数,调构造函数又要创建形参,....... void show() const{ cout << "data=" << data << endl; } virtual ~A(){ cout << "~A()" << endl; // show(200); // show(false); // show('A'); //A a2(28); //A a3(true); //A a4('S'); //A a5(a2); } }; void show( A obj) { obj.show(); } void func( const A& obj) { obj.show(); } int main() { A a1;//调用无参构造函数 show(a1); func(a1); }
当类无构造函数时,会自动产生A(),A(const A&)构造函数.
+ 当类成员有指针成员指向动态内存时默认拷贝构造函数会出问题.
因为它会使两个指针指向同一个地方导致混乱.
这时我们需要重写这个拷贝构造函数.如下示例:
#include <iostream> using namespace std; class A { int data; public : A():data(5){ //初始化列表初始化的是成员而不是形参 cout << "A()" << endl; } //拷贝构造函数 A(const A& o)/* :data(o.data) */ { cout << "A(const A&)" << endl; } void show(){ cout << "data=" << data << endl; } virtual ~A(){ cout << "~A()" << endl; } }; int main() { A a1; a1.show(); //输出正常 A a2(a1); a2.show(); //输出垃圾数据,所以初始化不能少 }
在类的成员函数中可以访问本类中任何成员变量.
自已定义拷贝构造函数之后,就没有默认的拷贝构造函数了,要在
自己定义的拷贝构造函数中处理所有需要处理的数据.
//动态数组类,长度可动态变化.未完整版 #include <iostream> using namespace std; class Array { char * p; int len; public : Array(int n ) : len(n),p(NULL){ resize(n); } Array( const Array& o ) : len(o.len) { p = new char[len]; for( int i=0; i<len; i++ ) p[i] = o.p[i]; } void resize( int n ){ char * q = new char[n]; int min = (n<len?n:len); if(p!=NULL){ for( int i=0; i<min; i++) q[i] = p[i]; delete[] p; } p = q; for( int i=min; i<n; i++) p[i] = '\0'; len = n; } int size(){ return len; } void set( int index, char c ){ if( index<0 || index>len ){ cout << "Error" << endl; return; } p[index] = c; } char get( int index ){ if( index<0 || index>len ){ cout << "Error" << endl; return '^'; } return p[index]; } void fill ( char start, int skip ){ for( int i=0; i<len; i++) p[i] = start + i*skip; } void show(){ for( int i=0; i<len; i++){ cout << p[i]; } } ~Array(){ if(p!=NULL){ delete[ ] p; p = NULL; } } }; //end class Array int main() { Array a1(10); a1.fill('a',2); a1.show(); cout << endl; Array a2(a1); a2.fill('A',2); a2.show(); cout << endl; a1.show(); cout << endl; cout << "------------------" << endl; cout << "Please input text(end by '$') : " << endl; for(int i=0;;i++){ char c; cin >> c; if(c=='$') break; else if(i+1>a1.size()){ a1.resize(a1.size()+10); } a1.set(i,c); } a1.show(); cout << endl; for( int i=0; i<a1.size(); i++){ cout << a1.get(i); } }
========================================
默认的拷贝构造函数是浅拷贝,自己写的拷贝构造函数是深拷贝.
* 运算符函数
* 单目运算符
A operator+(A obj1,Aobj2){/* code */}; A a1(30),a2(50); A result; result = a1 + a2; //会去调A operator+(A obj1,Aobj2) result.show();
//示例 //由程序可知成员比友员要方便,少传一个参数 #include <iostream> using namespace std; class A{ //code A sub( const A& o){ return A(data-o.data); } A oprator-()/...... }; A operator-(const A& o1, const A& o2){ //code... } int main() { A obj1(40),obj2(50); A obj3,obj4; obj3 = obj1.sub(obj2); obj3.show(); obj4 = obj1 - obj2; //会去调obj1.aperator-(..) }
运算符重载就是自已写运算符函数来规定运算符如何工作.
--------------------------
运算符函数的实现方法:
* 友元运算符函数:
- 在类中声明friend
- 定义:返回类型 operatorX(形参1,形参2)
- 调用: obj1 X obj2 解释成 operatorX(obj1,obj2),返回值作为运
算结果
* 成员函数: 直接在类中定义
- 定义: 返回类型 operatorX(形参1)
- 调用: obj1 X obj2 解释成 obj1.operator(obj2),返回值作为运算
结果
cout << f1 << f2;//用重载运算符表示,只能通过友员来实现
// 如果要用成员函数,则会有cout.operator<<(const F& f),所以这是不
// 可能的.因此只能用友员来实现,operator<<(cout,f)
// 而cout是ostream型的,因此有以下标准格式.注意不能加const,因为//
cout是要改变的,会改变里的缓冲成员.
ostream& operator<<( /* 不能加const */ ostream& cout, const
F&) //输出运算符的标准重载格式.
friend istream& operator>>(istream& is, F& f){
}//输入运算符重载标准格式
//重载运算符完整例子 //双目运算符重载 #include <iostream> using namespace std; class F{ int n; int d; public : F(int n=0, int d=1):n(n),d(d){} friend ostream& operator<<(ostream& os, const F& f){ os << '[' << f.n << '/' << f.d <<']'; return os; } F operator*(const F& o) { return F(n*o.n,d*o.d); } friend F operator/(const F& f1,const F& f2){ return F(f1.n*f2.d,f1.d*f2.n); } friend istream& operator>>(istream& is, F& f){ char ch; is >> f.n >> ch >> f.d; return is; } }; int main() { F f1(3,5),f2(11,7),f; cout << f1 << '*' << f2 << '=' << f1*f2 << endl; cout << f1 << '/' << f2 << '=' << f1/f2 << endl; cout << "Input 2 fractions :"; cin >> f1 >> f2; cout <<"f1=" << f1 << endl; cout << "f2=" << f2 << endl; }
* 单目运算符重载
-友元函数形式,返回类型 operatorX(形参)
使用:X obj ---> operatorX(obj);
-成员函数形式 尽量用成员 返回类型 operatorX(/*无形参*/)
使用: X obj ---> obj.operator();
//单目运算符重载 //把后++,后--当作双目运算符,第二个操作数是整形. #include <iostream> using namespace std; class A{ int data; public : A(int d=0):data(d){} friend ostream& operator<<(ostream& os,const A& a){ os << a.data; return os; } friend istream& operator>>(istream& is,A& a){ is >> a.data; return is; } friend A& operator++(A& a){ a.data += 10; return a; } A& operator--(){ data -= 10; return *this; } //后加加,规定一个整形为形参,与先加加区分 friend A/* 此时不再用引用 */ operator++(A& a,int){ A old(a); a.data += 1; return old; } //后减减,规定为一个整形为形参,与先减减区分. A /*不要引用*/ operator--(int){ A old(*this); data -= 1; return old; } }; int main() { A a1(50),a2(100); cout << "a1=" <<a1 << endl; cout << "a2=" <<a2 << endl; cout << "++a1=" << ++a1 << endl; cout << "--a1=" << --a1 << endl; cout << "a1++=" << a1++ << endl; cout << "a1=" <<a1 << endl; cout << "a2--=" << a2-- << endl; cout << "a2=" <<a2 << endl; }
运算符重载提供了一个自己规定运算符式作方式的方法,至少有一个操
作数是自定义类型的.基本类型我们是规定不了的.
强制类型转换:类型(数据) --> (不必写返回类型,因为始终与后面的类
型是相同的) operator类型(无形参) 只能写成成员函数,不能是友员.
#include<iostream> using namespace std; class A{ int data; public: A(int d=0):data(d){} operator int(){ return data; } operator bool(){ return data!=0; } operator char(){ return (char)data; } }; int main() { A a1(65),a2(200); cout << "a1=" << (char)a1 << endl; int d=a2; if(a2) cout << "good" << endl; }
对自定义类型的对象,使用运算符时,总是调用相应的运算符函数
三目运算符不能重载.
等号是双目运算符也可重载,它也只能是成员.
还有点号('.')不能重载.
双冒号(::)不能重载.
sizeof(类型)没法重载.
#号不是运算符,无所谓重载.
'= () [] -> 类型转换'只能是成员函数来重载,其它的随便,我们建议尽量
使用成员函数来写,有点只能用友元,比如输入输出.
==================================================
+ 双目运算符重载
- 友元形式:返 operator符号(形1,形2)
- 成员形式:返 operator符号(形)
+ 单目运算符重载
- 友元: 返 operator符号(形参)
- 成员: 返 operator符号()
+ 特例
- 加加
- 先加加
- 后加加 返回 operator符号(形,int)
- 减减
- 先减减
- 后减减
- 类型转换 只能是成员perator 空格 类型();
发表评论
-
UC++之目录和文件操作
2009-06-05 11:55 1246* UC + 文件系统 - 目 ... -
用c++实现二叉树增删改查和快速排序算法
2009-06-02 13:18 2583//快速排序 #include <iostream ... -
快速排序完整示例
2009-06-01 21:04 1076#include <iostream> usin ... -
C++容器与迭代器
2009-06-01 17:55 1975* 容器的迭代器还有几种: + iterator:正常迭 ... -
c++排序算法与模板和STL
2009-05-31 13:32 1808* 冒泡排序 一轮比较所有相邻数据对,如果顺序不合适就交换, ... -
C++算法与二叉树的实现
2009-05-30 18:35 2484* 输出格式控制 + 成员函数:width fill pr ... -
c++链表 异常 内部类 输出格式控制
2009-05-29 21:36 1676C(控制台) F(文件) ------------- ... -
C++之I/O
2009-05-27 21:26 1855* 重载 + 拷贝构造函数A(const A& o ... -
C++多态与类型转换
2009-05-25 17:10 1843c++中字符串的处理,用string进行处理,实际上它是一个类 ... -
类的继承
2009-05-24 09:42 9781,如何定义,实现一个类 ... -
面向对象编程
2009-05-23 19:20 697//倒计时 #include <iostr ... -
C++ 面向对象
2009-05-23 15:40 925* 指针简单总结 //接受命令行参数的函数 int main ... -
C与C++中的time相关函数
2009-05-23 14:03 1293本文从介绍基础概念入手,探讨了在C/C++中对日期和时间操作所 ... -
c++指针续
2009-05-23 11:16 960//常指针,或叫定指针:指 ... -
C++指针
2009-05-22 19:22 1158C++ 里有字符串类型string ,最大可支持1G,可用st ... -
数组本质
2009-05-21 18:52 1214数组是一片连续的内存空间,定义时一般指明大小和类型,这样编译器 ... -
C++用递归解决汉诺塔问题(续)
2009-05-19 12:16 914#include <iostream.h> ... -
c++ 递归实例二
2009-05-18 22:37 1646#include <iostream.h> ... -
C++用递归解决汉诺塔问题
2009-05-18 21:54 2538递归确实是一个不错的算法,可以将原来很复杂的问题简化.这里要注 ... -
C++ 入门
2009-05-15 21:31 0一次性修改LINUX环境变量:(bash)export $PA ...
相关推荐
1. 设计一个类SavingsAccount,定义一个静态数据成员记录存款的年利率(rate) 2. 参考附件资料《拷贝构造函数的调用》,创建一个包含double*的类 3. 建立类RationalNumber(分数类),使其具有如下的功能:
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数、什么情况下调用赋值运算符。最后,简单的分析了下深拷贝和浅拷贝的问题。有需要的朋友可以看下
C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象时,它...
练习对字符串的常用操作,进而加深对类的多态...进一步熟悉掌握对类的构造函数重载,拷贝构造的使用 目录: 程序代码实现部分: p2----p6 实验结果部分: P7 实验中遇到问题及解决方法: P7----P9 实验心得: P9
华为 C++ 培训资料 经典 ...word讲解C++语言中级教材讲授C++语言的运用技术,包括:类、对象之间的关系、对象的存储与布局、运算符重载、智能指针、仿函数、泛型编程,C++模式设计基本思想。下载看吧
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
浅谈c++构造函数问题,初始化和赋值问题详解C++ 拷贝构造函数和赋值运算符详解C++中对构造函数和赋值运算符的复制和移动操作C++中复制构造函数和重载赋值操作符总结深入C++中构造函数、拷贝构造函数、赋值操作符、析...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
在C++中, 构造函数,拷贝构造函数,析构函数和赋值函数(赋值运算符重载)是最基本不过的需要掌握的知识。 但是如果我问你“拷贝构造函数的参数为什么必须使用引用类型?”这个问题, 你会怎么回答? 或许你会回答...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
本文主要给大家介绍了关于C++默认成员函数与运算符重载的相关内容,分享出来公的敬爱啊参考学习,话不多说,来一起看看详细的介绍: 一:类和对象的基础知识:类的定义,访问限定符,面向对象封装性,对象的大小计算...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...
全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...