常用的:#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:是需要重载该运算符的类名!
@:是需要被重载的运算符