目录
类声明
//类是一种用户自定义类型,声明形式:
class 类名称
{
public:
公有成员(外部接口)
private:
私有成员
protected:
保护成员
};
公有、私有、保护成员
在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
在关键字protected后面声明,与private类似(基类成员可以访问,但是基类对象不能访问,派生成员和友元也可以访问但只能通过派生类的对象来访问基类部分受保护的部分。
受保护的成员
C++中使用protected关键字来声明那些它希望与派生类分享但是不想被其他公共访问使用的成员。protected可以看作是public和private中和的产物。
- 和private成员类似,受保护的成员对于类的用户来说是不可访问的
- 和public类似,受保护的成员对于派生类的成员和友元来说是可以访问的
- 派生类的成员和友元只能通过派生类对象来访问基类的受保护的成员。派生类对于一个基类对象中受保护的成员没有任何访问权限。
为理解最后一条,举例如下:
class Base
{
protected:
int prot_mem;
};
class Sneaky :public Base
{
friend void clobber(Sneaky&); //能访问Sneaky::prot_mem
friend void clobber(Base&); //不能访问Base::prot_mem
int j; //j默认是private
};
//正确:clobber能访问Sneaky的proteced和private成员
void clobber(Sneaky& s) {s.j = s.prot_mem = 0;}
//错误:clobber不能访问Base的proteced和private成员
void clobber(Base& b) {b.prot_mem = 0; }
派生类的成员和友元只能访问派生对象中的基类部分的受保护对象,对于普通的基类对象中的成员不具有特殊的访问权限。
公有、私有和受保护继承
某个类对其继承而来的成员的访问权限受两个因素影响:一是基类中该成员的访问说明符,二是派生类的派生列表中的访问说明符
class Base
{
public:
void pub_mem();
protected:
int prot_mem;
private:
char priv_mem;
};
class Pub_Derv :public Base
{
public:
//正确:派生类能够访问protected
int f() { return prot_mem; }
//错误:privated成员对于派生类是不可访问的
char g() { return priv_mem; }
};
class Priv_Derv :private Base
{ //private 不影响派生类的访问权限
public:
int f1() { return prot_mem; }
};
派生访问说明符对于派生类的成员(及友元)能否访问其直接基类的成员没有什么影响。对基类成员的访问权限只与基类中的访问说明符有关。派生访问说明符控制派生用户(包括派生类的派生类)对于基类的访问权限
Pub_Derv d1;
Priv_Derv d2;
d1.pub_mem(); //正确;pub_mem在派生类中是public
d1.prot_mem; //错误:prot_mem在派生类中是protected
d2.pub_mem(); //错误:pub_mem在派生类中是private的
派生访问说明符的目的是控制派生类的用户(包括派生类的派生类在内)对于基类成员的访问权限
struct Derived_from_public :public Pub_Derv
{
//正确 Base::prot_mem在Pub_Derv中任然是protected的
int use_base() { return prot_mem; }
};
struct Derived_from_private :public Priv_Derv
{
//错误 Base::prot_mem在Priv_Derv中是private的
int use_base() { return prot_mem; }
};
struct Derived_from_protected :public Prot_Derv
{
//错误 Base::prot_mem在Prot_Derv中任然是protected的
int use_base() { return prot_mem; }
};
数据抽象和封装
数据抽象是一种依赖于接口和实现分离的编程(和设计)技术。类设计者必须关心类是如何实现的,但使用该类的程序员不必了解这些细节。使用者只要抽象地考虑该类型做什么,而不必具体地考虑该类如何工作。
封装是一项将低层次的元素组合起来形成新的、高层次的实体的技术。函数是封装的一种形式:函数所执行的细节行为被封装在函数这个更大的实体中。被封装的元素隐藏了它们的实现细节——可以调用函数,但是不能直接访问函数所执行的语句。同样地,类也是一个封装的实体:它代表若干成员的聚集,设计良好的类隐藏了类实现的细节
内联成员函数
内联函数能够提高效率,编译的时候将代码直接嵌入到调用到的地方,从而见晒函数调用的开销,使得代码增大,以时间换空间,内敛函数必须短小,声明为内敛仅仅是给编译器一个提示,如果函数中有switch,for 这些语句的话,编译器将不会以内敛方式解释。
两种定义方式:一是直接在类体中定义,二是在内外部定义声明为inline
成员函数的重载及其缺省参数
注意带默认参数的重载函数要避免二义性
类与结构体
都是类,class与struct的区别:在未指定访问权限时,class默认的是私有的,struct默认是公有的
隐含的this指针
成员函数有一个隐含的附加形参,即指向该对象的指针,这个隐含的形参叫做this指针
使用this指针保证了每个对象可以拥有不同的数据成员,但处理这些成员的代码可以被所有对象共享
类作用域
每个类都定义了自己的作用域称为类作用域,类作用域中说明的标识符只在类中可见。
1、块作用域 如{ }以内 ,函数形参也是块作用域
2、文件作用域 函数之外
3、函数原型作用域 函数的声明的时候形参
4、函数作用域 goto语句
5、类作用域
前向声明
C++中类必须先定义,才能够实例化。
两个类需要相互引用形成一个“环形”引用时(A类中包含B类的头文件,B类中包含A类的头文件,无法先定义使用。这时候需要用到前向声明
前向声明的类不能实例化。可以定义指针或者引用
嵌套类
外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现
从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域外使用该类名时,需要加名字限定。
嵌套类中的成员函数可以在它的类体外定义。
嵌套类的成员函数对外围类的私有成员没有访问权,反之亦然。
嵌套类仅仅只是语法上的嵌入,在外界也可以使用
局部类
类也可以定义在函数体内,这样的类被称为局部类(loacl class)。局部类只在定义它的局部域内可见。
局部类的成员函数必须被定义在类体中。
局部类中不能有静态成员