一、类与对象
1.const 常函数,常量
#include<stdio.h>
class A{
public:
A( int a = 50,int data=1):b(data){//初始化表
this->a = a;
printf("AAAAA\n");
}
~A(){
printf("!~~~~~~~~~\n");
}
void show(void) const //常亮函数 ,不会对成员进行修改
{
printf("b = %d\n",b);
printf("a = %d\n",a);//证明常量函数可以打印非常量变量
a++; //因为是const函数,所以无法编译通过
}
private:
int a;
const int b;
};
int main(int argc, const char *argv[])
{
A x(2);
x.show();
A y(3);
y.show();
A z;
z.show();
return 0;
}
2.static 注意区分 类与对象
vbnet
#include<stdio.h>
class A{ //类
public:
static void func(void)//可以不依靠于对象而实现
{
printf("static \n");
}
static int data;
};
int A::data = 10;
int main(int argc, const char *argv[])
{
A a; //对象
a.func(); //基于对象可以调用
A::func(); //此为基于类的方式,若无static 则无法调用
A x; //对象
x.data = 100;//基于对象的赋值
A::data = 1000;//直接对类进行操作
return 0;
}
二、普通运算符重载
vbnet
#include<stdio.h>
#include<unistd.h>
class Timer{
public:
Timer()
{
hour = 0;
min = 0;
sec = 0;
}
~Timer()
{
}
void addtimer(int sec = 1)
{
this->min +=(this->sec + sec)/60;
this->sec = (this->sec + sec)%60;
}
void show()
{
printf("%2d:%2d:%2d\n",hour,min,sec);
}
Timer operator+(int sec)
{
Timer tem;
tem.sec = this->sec + sec; // t3 = t + 3
return tem;
}
Timer operator+(Timer &x)
{
Timer tem; //t2 = t + t1 tem代表的是t,参数中代表的是括号里面的参数
tem.sec = sec + x.sec;
tem.min = min + x.min;
tem.hour = hour + x.hour;
return tem;
}
Timer operator++(int) //后++
{
Timer tem = *this;//backup
sec++;
return tem;
}
Timer operator++() //前++
{
sec++;
return *this;
}
//若返回值是 对象,则无法被赋值
//若返回值是引用(加上&),则可以被赋值
int &operator[](int i)
{
switch(i)
{
case 0:
return hour;
case 1:
return min;
case 2:
return sec;
}
}
private:
int hour;
int min;
int sec;
};
int main(int argc, const char *argv[])
{
Timer t;
t.addtimer(3);
Timer t1;
t1.addtimer(5);
Timer t2;
t2 = t + t1;
t2.show();
/*
printf("hour:%d\n",t2[0]);
printf("min:%d\n",t2[1]);
printf("sec:%d\n",t2[2]);
t2[1] = 30;
printf("hour:%d\n",t2[0]);
printf("min:%d\n",t2[1]);
printf("sec:%d\n",t2[2]);
*/
Timer t3;
t3 = t + 3;
t3.show();
/*
Timer t;
while(1)
{
t.addtimer(100);
t.show();
sleep(1);
}
*/
return 0;
}
三、特殊运算符重载
3.1赋值运算符号
vbnet
#include<stdio.h>
#include<string.h>
class A{
public:
A()
{
printf("A()\n");
p = new char[10];
strcpy(p,"hello");
}
A(const A &x)//拷贝构造函数
{
printf("const A &x\n");
p = new char[10];
strcpy(p,x.p);
}
A & operator = (A &x) //赋值运算符
{
printf("const A &x\n");
p = new char[10];
strcpy(p,x.p);
}
~A()
{
printf("~A()\n");
delete []p;
}
private:
char *p;
};
int main(int argc, const char *argv[])
{
A x;
A y = x;
y = x;
return 0;
}
3.仿函数()
vbnet
#include<iostream>
using namespace std;
class Converter{
public:
Converter(double rate)
{
this->rate = rate;
}
double operator()(double rmb)
{
return rmb*rate;
}
private:
double rate;
};
int main(int argc, const char *argv[])
{
Converter RMBtoUS(6.3);
cout << RMBtoUS(10) << endl;
cout << RMBtoUS(10) << endl;
Converter RMBtoE(7.8);
cout << RMBtoE(10) << endl;
cout << RMBtoE(10) << endl;
return 0;
}
四、组合与继承
4.1 组合
main.cpp
#include"arr.h"
class Stuma{
public:
Stuma(){
}
~Stuma(){}
void savescore(int score)
{
scorearr.addtail(score);
}
void showscore(void)
{
scorearr.show();
}
private:
ARR scorearr; //在arr.c中已经实现了
};
int main(int argc, const char *argv[])
{
Stuma m;
m.savescore(22);
m.savescore(33);
m.showscore();
return 0;
}
arr.cpp
#include"arr.h"
#include<stdio.h>
void ARR::addtail(int data)
{
this->data[tail++] = data;
}
void ARR::show(void)
{
int i = 0;
for(;i<tail;i++)
printf("%d",data[i]);
printf("\n");
}
arr.h
#ifndef _ARR_
#define _ARR_
/*
typedef struct arr{
int data[100];
int tail;
void (*addtail)(struct arr *arr,int data);
void (*show)(struct arr *arr);
}ARR;
void init(struct arr *arr);
*/
class ARR{
public:
ARR():tail(0)//初始化表
{
}
void addtail(int data);
void show(void);
private:
int data[100];
int tail;
};
#endif
4.2 继承
#include<iostream>
using namespace std;
class A{ //基类
public:
A(){}
~A(){}
void showx()
{
cout<<"xxxxxxxxx\n"<<endl;
}
};
class AX:public A{ // 继承:派生类
public:
void showy()
{
cout<<"yyyyyyyyyyyy\n"<<endl;
}
};
int main(int argc, const char *argv[])
{
A a;
a.showx();
AX b;
b.showx();
b.showy();
return 0;
}
五、多态
#include<stdio.h>
class A{
public:
A(){
}
~A(){}
void show() //若为 virtual void show();作用:派生类会覆盖基类同名的函数
{
cout<<"AAAAAAAAA\n"<<endl;
}
};
class B:public A{
public:
void show()
{
cout<<"BBBBBBBBBB\n"<<endl;
}
};
int main(int argc, const char *argv[])
{
B b;
B *q = &b; //只认指针,不认对象
A *p = &b; // 支持用基类的指针 指向派生类的地址
return 0;
}
案例:计算各个周长的函数
#include<iostream>
using namespace std;
class shape{
public:
virtual double getC(void) = 0;
//设为纯虚拟函数
//此基类主要是为了提供接口
};
class cir:public shape{ //继承类
public:
cir(double ri):r(ri){}//构造函数直接赋值
double getC(void)
{
return 2*3.14*r;
}
private:
int r;
};
class tri:public shape{
public:
tri(double a,double b,double c):e1(a),e2(b),e3(c){}
double getC(void)
{
return e1+e2+e3;
}
private:
double e1;
double e2;
double e3;
};
class rec:public shape{
public:
rec(double e)
{
this->e = e;
}
double getC(void)
{
return 4*e;
}
private:
double e;
};
double countC(shape *arr[],int n)
{
double sum = 0;
for(int i = 0;i<n;i++)
{
sum += arr[i]->getC();
}
return sum;
}
int main(int argc, const char *argv[])
{
cir c(1);
rec r(3);
cir c1(2);
tri t(3,3,3);
shape *arr[] = {&c,&r,&c1,&t};
cout<<"total c:"<<countC(arr,4)<<endl;
return 0;
}
六、异常
vbnet
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<exception>
using namespace std;
class argexception:public exception{
public:
const char* what() const throw()//不抛异常函数
{
return "arg Err !";
}
};
int myatoi(const char *str)//后面没有throw表示什么异常都可以抛
{
if(*str <'0' || *str > '9')
throw argexception();
else
return atoi(str);
}
int main(int argc, const char *argv[])
{
try{
int data = myatoi("asfsa");
cout << data << endl;
}
catch (argexception e)
{
cout << e.what() <<endl;
}
return 0;
}
七、 转换函数
7.1 自定义转换
#include<stdio.h>
#include<unistd.h>
#include<iostream>
using namespace std;
class Timer{
public:
Timer()
{
hour = 0;
min = 0;
sec = 0;
}
~Timer()
{
}
void addtimer(int sec = 1)
{
this->min +=(this->sec + sec)/60;
this->sec = (this->sec + sec)%60;
}
operator int() //自定义强转类型符
{
return sec + min*60 + hour *60*60;
}
private:
int hour;
int min;
int sec;
};
int main(int argc, const char *argv[])
{
Timer t;
t.addtimer(3);
int sec = t;
cout << sec << endl;
return 0;
}
7.2 隐式转换
#include<iostream>
using namespace std;
class mempool{
public:
explicit mempool(int size){
data = new char[size];
cout<<"this is 隐式转换"<<endl;
}
~mempool()
{
delete []data;
}
private:
char *data;
};
int main(int argc, const char *argv[])
{
mempool a(100);
//mempool a = 100; //此语句也会调用构造函数,为了防止隐士转换,函数前加上expiicit
return 0;
}
八、模版
#include<stdio.h>
#include<iostream>
using namespace std;
#if 0
int add(int a,int b)
{
return a+b;
}
double add(double a,double b)
{
return a+b;
}
#endif
template<typename xxx>
xxx add(xxx a,xxx b)
{
return a+b;
}
int main(int argc, const char *argv[])
{
cout<< add(1,2)<< endl;
cout<< add(1.1,2.3) << endl;
return 0;
}
九、STL算法
9.1、迭代器
#include <iostream>
#include <ostream>
using namespace std;
class myList{
struct Node{
Node(int x, Node *ptr=NULL):data(x), next(ptr) { }
int data;
Node *next;
};
public:
class iterator{
public:
iterator(Node *ptr=NULL):pos(ptr) { }
iterator &operator++(int)
{
if(NULL != pos)
pos = pos->next;
return *this;
}
int &operator*()
{
return pos->data;
}
bool operator!=(iterator x)
{
return pos != x.pos;
}
private:
Node *pos;
};
public:
myList():head(NULL) { }
~myList() {
while(head)
{
Node *tem = head;
head = head->next;
delete tem;
}
}
void insert_head(int data)
{
Node *node = new Node(data);
node->next = head;
head = node;
}
iterator begin()
{
return iterator(head);
}
iterator end()
{
return iterator(NULL);
}
friend ostream &operator<<(ostream &out, const myList &list);
private:
Node *head;
};
ostream &operator<<(ostream &out, const myList &list)
{
myList::Node *tem = list.head;
while(tem)
{
out<< tem->data <<',';
tem = tem->next;
}
out << endl;
return out;
}
int main()
{
myList list;
list.insert_head(1);
list.insert_head(2);
list.insert_head(4);
list.insert_head(3);
cout << list;
myList::iterator i = list.begin();
while(i != list.end() )
{
cout << *i <<endl;
i++;
}
}
链表功能的实现
#include<iostream>
#include<ostream>
using namespace std;
class myList{
struct Node{//struct声明的默认为public
Node(int x,Node *ptr = NULL):data(x),next(ptr){}
int data;
Node *next;
};
public:
myList():head(NULL){}//链表的表头初始化为null
~myList()
{
while(head)
{
Node *tem = head;
head = head->next;
delete tem;
}
}
void insert_head(int data)
{
Node *node = new Node(data);//在堆中分配这个节点并赋值
node->next = head;
head = node;
}
friend ostream &operator<<(ostream &out,const myList &list);
private:
Node *head;
};
// 对 << (输出字符) 的运算符重载
ostream &operator<<(ostream &out,const myList &list)
{
myList::Node *tem = list.head;
while(tem)
{
out<<tem->data<<',';
tem = tem->next;
}
out << endl;
return out;
}
int main(int argc, const char *argv[])
{
myList list;
list.insert_head(1);
list.insert_head(3);
list.insert_head(2);
list.insert_head(5);
cout << list;
return 0;
}
9.2、STL容器
例:迭代器和链表算法
#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main(int argc, const char *argv[])
{
#if 0
vector<int> arr;//迭代器的使用
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
arr.push_back(4);
#endif
//vector<double> arr;
list<double> arr;
arr.push_back(2.3);
arr.push_back(2.3);
arr.push_back(2.3);
arr.push_back(2.3);
//vector<int>::iterator i = arr.begin();
//vector<double>::iterator i = arr.begin();
list<double>::iterator i = arr.begin();//链表的使用
while(i != arr.end())
{
cout<< *i<<endl;
i++;
}
return 0;
}
注意事项:
1.类中:若出现有参数的构造函数,则需要一个无参数的构造函数
2.新对象产生一定调用了构造函数
3.构造函数:a.无参数的 b.有参数的 c.拷贝构造函数
4.静态函数:基于类 而不是基于对象实现的方式
5.c++最好使用++i,少用i++
6.对象生成的时候才会调用构造函数