常用的:#include<iostream.h>
#include<iomanip.h>中
定义了流控制符,来控制数据的输出格式
Dec Hex Oct 分别为十进制 十六进制 八进制
setw(n)输出域宽为n
setfill(c)在给定的输出宽度内,填充字符c
........等
例:cout<<setw(3)<<setfill('#')<<hex<<a<<endl;
cout<<setw(4)<<b<<endl;
注意在定义了setfil,hex..之后,(在新的定义来之前)所有的语句都按照改定义执行
如:上面的第二句,同样以十六进制吗,填充‘#’的方式输出。
内敛函数 inline:调用这样的函数时,把代码直接插入到调用点,而没有程序跳转,返回一系列问题了
这样的函数中,不能有复杂的语句 如:switch while,不能递归
一般只有1~5行语句的小函数
重载函数:(对于一些具有同一功能的函数,但函数参数不同)
即,可以定义一些函数名相同的函数,但至少形参的个数,类型或顺序上不同。
在调用时,传入相应的实参,系统就可以和传入的实参分辩,调用相应的正确的函数!
默认参数的函数:P78 :不传入参数的话,就用默认参数!!
例:
#include<>
void sum(int num=10);//如果有函数说明,默认参数就在说明中提供
void main()
{
sum(100);//用100传入
sum();//使用默认参数
}
void sum(int num)//这里就不用提供默认参数了
{
}
关于const指针:
1.指向只读数据的指针变量!
const int *p;
即:指针指向的数据不能写入(改变),但指针可以改变指向!
2.指针常量
char *const p="adcfdg";
用这种方法定义的指针变量,指针指向不能改变,但指针所指的数据内容可以改变。
如:(接上) p="xtyz" //错的,它改变了指针的指向!
(接上) *p='s'; //对的(多了个*),只是改变了指向内容的值!
3.指向常量的指针常量
顾名思义:指向不能改变,指的内容也不能改变
引用:
int a ;
int &ra=a;
从此ra是a的别名!!
引用作为函数的参数:
void swap(int &p1,int &p2)
{.....}
调用函数,实参传给两个引用,函数中对p1,p2的操作就是直接对两个实参的操作!
注意:p1,p2不会分配内存。而用一般变量传递函数,会分配内存!
有关内存分配:
看例子:
#include<iostream.h>
#include<stdlib.h>
int *number,*p,*q;
number=new int[100];//分配一个有100个int型元素的数组!!!!
p=new int(11);//分配一个int型的内存空间,初值为11
q=(int*)malloc(10*sizeof(int));
if(nmber==NULL||p=NULL||q==NULL)
{
cout<<"内存分配失败"<<endl;
}
else ;
delete []number;//注意这个写法!!!
delete p;
free(q);
构造函数:
其在类中,且函数名与类名相同,用于在对象定义时,自动被调用给对象初始化。
例:
class Person
{
private:.......
public:
Person(XXX,XXX,XXX,XXX);
.....
}
void Person::Person(XXX,XXX,XXX,XXX)
{
.........
//给相应的数据成员赋值
}
void main()
{
Person obj("zoushuai",XXX,XXX,XXX);//定义对象,带上初始值。
//之后,就定义并生成对象obj,然后自动调用构造函数Person.再将初始值传递给构造函数相应的形参!,最后执行构造
//函数体,将相应的值附给相应的数据成员!!!
}
析构函数:
同构造函数(为对象分配相应资源)功能相反,析构函数用来释放之前分配的资源!
函数如下:其被系统自动调用!如果在类的对象中没有分配动态内存(new),可以用系统提供的默认的析构函数.(如果程序员在类中,没有为类提供析构函数,就会默认生成一个。你看不到,但存在!)。如果有!:则必须为该类提供析构函数以完成清理工作(delete)!
~类名()
{
//函数体
}
利用初始化表对常量数据成员或引用成员提供初值!
例:
class Silly
{
public:
Silly()//这样的构造函数是错误的!
{
ten=10;
refi=i;
}
protected:
const int ten;//常量数据成员
int &refi;//引用refi
}
上面的是错误的:因为,在构造函数执行之前,对象结构已经建立(已生成),数据成员已存在,而且,ten是const只读的! refi为引用!在构造函数内是不能在对其指派新值的!
但可以这样:
在类外定义时:(在类内的public中即写:Silly();实现则在类外!如下)
Silly::Silly():ten(123),refi(i)//数据成员名(值),数据成员名(值),。。。。。。。
{}
继承与派生:原来类的程序代码可通过继承而在新类中得到重用。
在基类的基础上定义其派生类的定义形式:
class 派生类名(自定): 访问方式 基类名
{派生类中的新成员}//即,在基类的基础上可以添加新的成员
“访问方式”即继承方式 可以使private(私有继承)和public(共有继承) ,如果省略则是private
基类与派生类的关系
按public方式继承时:基类中的共有成员和保护成员在派生类中不变
按private方式继承时:基类中的共有成员和保护成员在派生类中都为私有成员
基类中的私有成员在派生类中是不可访问的!!!!!!!!!!!!!
基类的构造函数是不会被继承的!!
所以,在设计派生类的对象时,派生类的构造函数除初始化其自身定义的数据成员外,还必须对基类中的数据成员进行初始化(即还要调用基类的构造函数!!!)
派生类名::派生类构造函数名(参数表):基类构造函数名(参数表)
{。。。。。。。。。。。。}
注:派生类构造函数的参数中包括参数的类型和参数名,而基类构造函数的参数中只有参数名!而且这些参数必须来源于派生类构造函数名后面括号后的参数(即要在派生类构造函数参数表中定义)。
多重继承:
class 派生类名:访问方式 基类名1,访问方式 基类名2......
{..........}
在多重继承下,系统首先执行各基类的构造函数,再是派生类的。。。。。。。。。
虚基类:
它是这样的:它虽然被一个派生类间接地多次继承,但派生类却只继承一份该基类的成员。
将一个基类声明为虚基类:
class 派生类名: virtual 访问方式 基类名
{//声明派生类成员}
虚函数:
因为用基类指针指向公有派生类对象,指针仅能看到派生类中的基类部分。但是,如果做以下改变。能访问的就不同了。
虚函数的定义:
class 类名
{
public:
virtual 类型 函数名(参数表)
{。。。。。;}
。。。。。。
}
当一个类的成员函数声明为虚函数后(如上),就可以在该类的派生类中定义与其基类虚函数原型相同的函数(函数名,返回类型,参数个数等完全相同)(虽然没有加上关键字virtual,都将被视为虚函数)。这时,当用基类指针指向这些派生类对象时,系统会在程序运行过程中,动态的自动选择函数,从而实现了运行时的多态性。(当通过基类指针多次调用虚函数时,由于指针所指向对象的不同,而调用不同对象所属类的虚函数)。
纯虚函数:
纯虚函数的声明如下:
virtual 函数原型=0;
纯虚函数 是只在基类中声明但未给出具体的函数的实现,因此,用带有纯虚函数的基类中派生出的派生类,都必须定义与纯虚函数同名的重载函数。(这样,基类只是用于继承,仅作为一个接口,具体功能在派生类中实现!)
例子:
class Shape
{
protected:
........
public:
.........
virtual void area()=0;//声明纯虚函数
};
class Triangle : public Shape
{
public:
void area()
{cout<<"dddddd"<<endl}
};
class Rect : public Shape
{
public:
void area()
{cout<<"gggggg"<<endl}
};
void main()
{
Sharp *p;
Triangle r;
Rect t;
p=&r;
p->area();//调用相应的函数!
p=&t;
p->area();//调用相应的函数!
}
声明了纯虚函数的类,称为抽象类。
注意:
抽象类不能声明对象,只能用来派生。
抽象类中可以有多个纯虚函数
抽象类中也可以定义其他非纯虚函数
友元函数:
用friend 前缀声明的函数(在类的定义中声明(在private或public中声明没有区别)),该函数就可以访问,类的私有成员了! 这个函数不是类的成员函数!
友元类:
friend class B
在一个A类中,把另一个B类定义为友元类,则B类就可以访问A类中的私有元素了!
类模块:
基本语法:template <类型形式参数表> class 类模块名
例:
#include<iostream.h>
//定义类模块ABC
template <class T,int I> class ABC
{
private :
T arrat[I];
public:
........
}
void main()
{
ABC<int,100>abc2;//由模板ABC生成对象abc2!这样即生成了int 类型的大小为100的一个数组!!!就有这样的方便
}
函数模块:
和上面相似:
template <class>T min(T x,T y)
{
return x<y?x:y ;
}
调用时:
a=min(20,10);
b=min('A','a');
就是取消了类型的限制。 还可以带来许多的方便,自己慢慢想想(ˇˍˇ) 想~
运算符的重载:(即把已有的运算符在指定的类中,定义为其他的功能!)
语法格式如下:
TYPE X::operator @(形参表)
{
//函数体 重新定义运算符@在指定类X中的功能!
}
TYPE:返回值类型
X:是需要重载该运算符的类名!
@:是需要被重载的运算符