复制构造函数
深复制
深复制和赋值构造符重载二者类似
Country(const Country& c) { landArea = c.landArea; name = new char[strlen(c.name)+1]; strcpy(name, c.name); }
// 赋值运算符重载函数 ClassA& operator=(const ClassA& cls) { // 避免自赋值 if (this != &cls) { // 避免内存泄露 if (pszTestStr != NULL) { delete pszTestStr; pszTestStr = NULL; } pszTestStr = new char[strlen(cls.pszTestStr) + 1]; strncpy(pszTestStr, cls.pszTestStr, strlen(cls.pszTestStr) + 1); } return *this; }
浅复制
执行默认复制构造函数,只是对数据成员赋值,也就是这两个指针指向了堆里的同一个空间。
动态内存分配
用new和delete运算符进行动态内存分配
Square *p1; p1 = new Square; delete p1; p1 = new Square[2]; delete[] p1;
this指针
与重载运算符一起使用
Complex operator+(Complex& as) { Complex bs = *this; bs.real += as.real; bs.image += as.image; return bs; }
静态成员
含义:属于类所有对象共享,非某对象特有说明和定义规则(静态数据成员在类外初始化)
静态数据成员初始化:
数据类型 类名::静态数据成员名 = 初值
静态成员的访问方式(类域、对象)
静态成员属于类,无 this 指针特性
静态成员函数只能直接访问静态成员
静态成员函数类外定义
void Test::Print(Test& a){...}静态成员函数调用:
Test::Print(a); b.Print(a);
友元函数
friend ostream& operator<<(ostream& os, Rational& rhs) { os << rhs.nr << "/" << rhs.dm; return os; }
friend Complex operator+(double x, Complex& as) { Complex bs = as; bs.real += x; return bs; }
常对象
常对象只能调用常成员函数。 常成员函数体内不能对数据成员做任何改动。
派生
在派生类中访问基类中的同名成员
基类名::成员名
虚基类
virtual
初始化列表
赋值兼容规则
• 在类的继承层次关系图中,下层类对象可以赋值给上层类对象(对象、指针、引用)
• 派生类对象可以赋值给基类对象
• 派生类对象可以初始化基类对象引用
• 派生类对象地址可以赋值给基类对象指针
多态
编译时多态(静态多态性和静态联编)
函数重载
懂
运算符重载
• 友元运算符函数
aa@bb↔operator@(aa,bb), @aa↔operator@(aa)
• 成员运算符函数
aa@bb↔aa.operator@(bb), @aa↔aa.operator@()
实例见上文
函数模板
正常
template <typename T> T max(T a, T b) { return a>b?a:b; }
重载
template <typename T> T max(T a, T b) { return a>b?a:b; } char* max(char* a, char* b) { if(strcmp(a, b)>0)return a; else return b; }
特化
template<> char* max<char*>(char* a, char* b) { return (strcmp(a,b)>0?a:b); }
调用时与正常函数调用相同
运行时多态(动态多态性和动态联编)
继承
懂
虚函数
在基类定义中,必须将成员函数定义为虚函数,即在前面加“virtual”
派生类里,对虚函数的更新定义只能修改函数体内容,其它与基类虚函数完全相同
必须用指向基类的指针(或引用)访问虚函数
纯虚函数
virtual 函数原型 = 0;
抽象类只能用作基类来派生新类,而不能用来创建对象,但可以声明指针和引用
抽象类里可以有纯虚函数和非纯虚函数共存
派生类中必须给出所有纯虚函数的具体定义,或者仍旧将原基类中的纯虚函数声明为纯虚函数,必须要写出来
抽象类可以派生出抽象类或具体类,但是具体类不能派生出抽象类
类模板
定义和使用实例
#include <iostream> using namespace std; tempalte <typename T> class List //定义通用单链表模板 { public: List(); //构造函数 void Add(T&); //增加节点 void Remove(T&); //删除节点 void PrintList(); //打印链表 ~List(); //析构函数 protected: struct Node{ //定义结点的结构类型 Node *pNext //指向下一个结点的指针成员 T data; //本结点的数据成员 } Node* pHead; //指向链表头结点的指针 }; template<typename T> List<T>::List() { pHead = NULL; } template<typename T> void List<T>::Add(T& t) { Node* temp = new Node; temp->data = t; temp->pNext = pHead; pHead = temp; } template<typename T> void List<T>::Remove(T& t) { Node* q = 0; if((pHead->data)==t) { q=pHead; pHead=pHead->pNext; } else { for(Node* p=pHead;p->Next;p=p->Next) if((p->pNext->data)==t) { q=p->Next; p->pNext=q->pNext; break; } } if(q)//待删除结点在链中存在 { delete q; } } template<typename T> void List<T>::PrintList() { for(Node* p=pHead;p;p=p->Next) { cout<<(p->data)<<" "; } cout<<endl; } template<typename T> List<T>::~List() { Node* p; while(pHead!=NULL) { p=pHead; pHead=pHead->pNext; delete p; } } int main() { List<int> intList; //将所有的T全部替换为int,并创建对象intList List<char> charList; //将所有的T全部替换为char,并创建对象charList List<double> doubleList; //将所有的T全部替换为double,并创建对象coubleList ... }
派生
//类模板派生出类模板 template <typename T> class Base { ... }; template <typename> class Derived:public Base<T> { ... }; //类模板派生出普通类 template <typename T> class Base { ... }; class Derived:public Base<int> { ... }; //普通类派生出类模板 class Base { ... }; template <typename T> class Derived:public Base { T data; ... }
特化
C++流类库和I/O(看小雅ppt)
streambuf类和ios类
格式化输入和输出
成员函数(setf、unsetf、width、precision、fill)
操作符(endl、setw、setfill、setprecision)
文件的输入输出
文件的打开(ifstream、ofstream、fstream)ifstrea. in;in.open("in.dat"); ifstream in("in.dat")
文件的打开方式
文件的关闭(close)
文件尾的判断(if(!in.eof())、if(!in))
文件的读写
二进制文件的读写
文本文件的读写