C++语法点

函数

1.带默认形参值的函数,默认形参值必须按从右向左定义,实参从做到右初始化

int add(int x, int y=5, int z=6){} 
add(1); //y和z使用默认形参值

默认形参值可以通过函数声明在不同作用域中设置不同的值
2.函数模板

template 

函数定义
eg:

template 
T abs(T x)
{
	return x<0?-x,x;
}

类和对象

1.类的声明

class 类名称
{
public:
	外部接口
protected:
	保护型成员
private:
	私有成员
}

public声明类的外部接口,任何来自外部的访问都必须通过这个外部接口来进行
private成员只允许本类的成员函数访问,类外部的任何访问都是非法的
protected成员可以被继承的新类访问

2.类成员函数声明

返回值类型 类名:函数成员名(参数表)
{
	函数体
}

内联成员函数:与java不同,C++类体中只包含变量和函数的声明,带函数的定义的函数被隐式声明为inline函数,类体外内联函数的声明需要加inline关键字

3.构造函数和析构函数
构造函数的函数名和类名相同,没有返回值,可以是内联函数,支持重载。
java有内存自动回收机制,因此所有类的创建都使用“类名 对象名 = new 类名(参数列表);”的方式创建
C++的new不会自动回收,但是可以在指定作用域内通过"类名 对象名(参数列表);"定义局部类,此时的对象名作为一块栈内存的指针,不像new出来的对象名指向堆内存,因此不可以直接被return,系统会调用拷贝构造函数

拷贝构造函数形参是本类对象的引用,作用是使用一个已经存在的对象去初始化一个新的同类对象:

class 类名称
{
public:
	类名(参数表);			//拷贝函数
	类名(类名 &对象名);	//拷贝构造函数
}
类名::类名(类名 &对象名)	//拷贝构造函数的实现
{
	函数体
}

拷贝构造函数在对象作为形参或者作为对象作为返回值的时候被自动调用

析构函数是在对象的生命期即将结束的时刻由系统自动调用的,不接受任何参数,可以是虚函数。

~类名()
{
	函数体
}

java有内存自动回收,因此类不需要析构函数,finalize()成员作为内存释放的hook函数

如果类具有内嵌对象成员(聚合关系),且需要对内嵌对象成员进行初始化,构造函数定义为:

类名::类名(参数表):内嵌对象1(参数表),内嵌对象2(参数表),...(单冒号:后面跟的是类成员的初始化值,这里传入对象即调用内嵌对象的拷贝构造函数)
{
	类的初始化
}

eg:

class Distance
{
public:
	Distance(Point xp1, Point xp2);
private:
	Point p1,p2;
}
Distance::Distance(Point xp1, Point xp2):p1(xp1),p2(xp2)
{
	cout<<"Distance构造函数"<

调用顺序为先按照内嵌对象在组合类的声明中出现的次序,依次调用内嵌对象的构造函数,最后执行本类的构造函数的函数体,析构函数的顺序则相反。

4.类模板

template <模板参数表>

类声明

模板<模板参数表> 对象名1,...,对象名n

eg:

template 
class Store			//类模板
{
private:
	T item;
	int haveValue;
public:
	Store(void);
}
template 
Store::Store(void):haveValue(0) //函数模板实现的构造函数
{}
Store S1,S2;  //类模板调用

5.UML图
Coad/Yourdon标记中类使用带有圆角的矩形表示;
对象标记在类标记外加一个带有圆角的矩形框;
带实心箭头表示消息联系,箭头方向是消息接收方;
带空心半圆表示继承关系,半圆方向是父类;
带空心三角形表示包含关系,三角方向是外部类;

6.静态成员

C++中的静态成员不能像java一样使用类名访问,需要使用类限定符如Point::countP = 0;

7.友元
友元关系不可传递,单向的。
友元函数是在类声明中由关键字friend修饰的非成员函数,在它的函数体中可以通过对象名访问类的私有和保护成员。
若A类是B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。

8.常量
常引用所引用的对象不能被更新,比如常引用作为形参,在函数中不能更新该引用引用的对象;
常对象必须进行初始化,而且不能被更新,常对象只能调用它的常成员函数,不能调用其他成员函数;
常成员函数说明格式:

类型说明符 函数名(参数表)const;

常成员函数不能更新对象数据成员,也不能调用非const修饰的成员函数
const关键字可以被用于参与对重载函数的区分,eg:

R a(5);
a.print();  //调用 void print()
const R b(4);
b.print(); //调用 void print() const

继承与派生

1.派生类(子类)的声明语法:

class 派生类名:继承方式 基类名1,继承方式 基类名2,...,继承方式 基类名n
{
	派生类成员声明;
};

同时继承多个类是c++独有的特性,java只能继承一个类
继承过程中,如果派生类声明了一个和某个基类成员同名的新成员,派生的新成员就覆盖了外层同名成员(如果是成员函数,参数表不同则属于重载,否则属于覆盖)。

2.访问控制
1.公有继承,基类的公有和保护成员的访问属性在派生类中不变,而基类的私有成员不可访问。
2.私有继承,基类的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类中不可访问。
3.保护继承,基类的公有成员和保护成员都以保护成员身份出现在派生类中,而基类的私有成员在派生类中不可访问。

3.派生类构造函数

派生类名::派生类名(参数总表):基类名(参数表1),...,基类名n(参数表n),内嵌对象名1(内嵌对象参数表1),...,内嵌对象m(内嵌对象参数表m)
{
	派生类新增成员的初始化语句;
}

上述定义中,内嵌对象名和基类名顺序是随意的,实际调用顺序是先基类构造函数(按照派生类声明时的顺序),后调用内嵌对象构造函数(按照成员在类中的声明顺序)。
析构函数的执行顺序与构造函数正好严格相反。

4.多继承下成员访问
4.1 多个不同基类(这些基类没有共同父类)的同名成员或者被覆盖的同名成员,可以通过类作用域分辨
eg:

D1 d1;
d1.nV = 1;		//访问子类自身的
d1.B1::nV = 2;  //访问B1基类成员
d1.B2::nV = 3;  //访问B2基类成员

4.2 如果某个派生类的部分或者全部直接基类从另一个共同的基类派生而来,这些基类继承下来的成员就有相同名称的多个不同副本,此时必须使用直接基类进行限定
比如B1和B2有共同基类B0,B0中有变量nV,D1同时继承B1和B2,则

D1 d1;
d1.B1::nV=2;	//使用直接基类B1和B2限定
d1.B2::nV=3;

java中父类被覆盖的成员只能通过巧用super()来实现访问,无法直接访问

5.虚基类
如4.2所述问题,将共同基类设置为虚基类,这时从不同路径继承过来的同名数据成员就只有一个拷贝
class 派生类名:virtual 继承方式 基类名
此时将上述B1和B2继承方式声明为

class B1:virtual public B0{}
class B2:virtual public B0{}
d1.nV=2; //则d1中只有一个副本,可以使用d1.nV进行访问

虚基类的构造函数会在最远派生类构造函数(D1)之外的构造函数(B1和B2)被自动忽略,保证只被调用一次

6.赋值兼容
需要基类对象的任何地方可以使用公有派生类对象进行替代,替代后只能使用从基类继承的成员。

多态

1.运算符重载
语法:

[friend] 函数类型 operator 运算符(参数表) //声明为成员函数,操作数减1,声明为友元函数,操作数不便
{
	函数体;
}

eg:

complex complex::operator +(complex c2){}            //成员函数
friend complex operator +(complex c1, complex c2){}  //友元函数

2.虚函数
语法:

virtual 函数类型 函数名(形参表)
{
	函数体
}

虚函数声明只能出现在类声明中的函数原型声明中,不能出现在成员的函数体实现中
eg:

class B0
{
public:
	virtual void display(){cout << "B0::display()"<display(); //B0中的display()
p=&b1;
p->display(); //B1中的display()

java中可以直接用父类引用指向子类对象,通过调用被覆盖的成员实现多态,这是因为在java中父类被覆盖的成员,对于子类来说是透明的,因此无需虚函数
C++的多态是在上述“6.赋值兼容”的条件下,满足指针访问和虚函数的条件下,才能够实现。
C++中不能声明虚构造函数,但能声明虚析构函数。

3.抽象类
纯虚函数有点类似java的抽象函数,没有函数体:

virtual 函数类型 函数名(参数表)=0;

带有纯虚函数的类是抽象类。

群体类

1.线性群体
1.1.数组类:Array A(10);
1.2.链表类:Node *head=NULL;
1.3.栈类:Stack S;
1.4.循环队列类:Queue Q;
2.容器
2.1向量:vector vint;
2.2双端队列:dqueue dqueue;
2.3标准栈:Stack Sk;
2.4标准队列:queue MyQueue;
2.5列表:list Link;

异常处理

语法:

throw 表达式
try
	复合语句
catch(异常类型声明)
	复合语句
catch(异常类型声明)
	复合语句
	...

你可能感兴趣的:(编程语言)