一、类定义
类包含类头和类体,类头就是class和类名,类体就是大括号中的内容
每个类定义引入一个不同的类 class 类型,即使两个类类型具有完全相同的成员表它们仍是不同的类型,例如:
class First {
int memi;
double memd;
};
class Second {
int memi;
double memd;
};
class First obj1;
Second obj2 = obj1; // 错误: obj1 和 obj2 类型不同
在引入类类型之后,我们可以以两种方式引用这种类类型:
1 指定关键字class 后面紧跟类名,在前面例子中obj1 的声明以这种方式引用类 First。
2 只指定类名,在前面例子中obj2 的声明以这种方式引用Second这两种引用类类型的方式是等价的,第一种方式是从 C 中借用的,在 C++的声明中用它引用类类型也是有效的,第二种方式是 C++引入的,它使类类型更容易被用在声明中。
二、成员函数
1.类的成员函数被声明在类体中。
2. 成员函数的定义也可以被放在类体内。
3.成员函数被声明在它的类中,这意味着该成员函数名在类域之外是不可见的,我们可以通过,点 . 或箭头 -> 成员访问操作符,引用成员函数
4.成员函数拥有访问该类的公有和私有成员的特权,而一般来说,普通函数只能访问类的公有成员,一般而言,一个类的成员函数对另一个类的成员没有访问特权成员函数可以是重载的函数,但是,一个成员函数只能重载自己类的其他成员函数,一个类的成员函数与在其他类或名字空间中声明的函数无关,因此,也不能重载它们
5.类成员的访问限制是通过类体内被标记为 public、 private 以及 protected的部分来指定的 关键字 public、 private 和 protected 被称为访问限定符,在公有 public 区内被声明的成员是公有成员 在私有 private 或被保护的 protected区域内被声明的成员是私有或被保护的成员
(1)公有成员: public在程序的任何地方都可以被访问,实行信息隐藏的类将其 public 成员限制在成员函数上,这种函数定义了可以被一般程序用来操纵该类类型对象的操作。
(2) 私有成员: private只能被成员函数和类的友元访问,实行信息隐藏的类把其数据成员声明为 private。
(3)被保护成员: protected对派生类 derived class 就像 public 成员一样,对其他程序则表现得像 private。
三、友元
在某些情况下,允许某个函数而不是整个程序可以访问类的私有成员,这样做会比较方便,友元 friend 机制允许一个类授权其他的函数访问它的非公有成员。
友元声明以关键字 friend 开头,它只能出现在类的声明中,由于友元不是授权友谊的类的成员,所以它们不受其在类体中被声明的 public private 和 protected 区的影响。
class Screen {
friend istream &
operator>>( istream&, Screen &);
friend ostream &
operator<< ( ostream&, const Screen&);
public:
// ... Screen 类的其他部分
};
一个友元或许是一个名字空间函数,另一个前面定义的类的一个成员函数,也可能是一个完整的类,在使一个类成为友元时,友元类的所有成员函数都被给予访问“授权友谊的类的非公有成员”的权力。
四、类的声明和定义
class Screen ; // Screen 类的声明
如果没有定义,那么我们就不能定义这类类型的对象,因为类类型的大小不知道,编译器不知道为这种类型的对象预留多少存储空间。
但是,我们可以声明指向该类类型的指针或引用,允许指针和引用是因为它们都有固定的大小,这与它们指向的对象的大小无关,但是,因为该类的大小和类成员都是未知的,所以要等到完全定义了该类,我们才能将解引用操作符 * 应用在这样的指针上,或者使用指针或引用来指向某一个类成员。
只有已经看到了一个类的定义,我们才能把一个数据成员声明成该类的对象,在程序文本中还没有看到该类定义的地方,数据成员只能是该类类型的指针或引用,例如下面是类StackScreen 的定义,它有一个数据成员是指向 Screen 类的指针,这里 Screen 只有声明没有定义。
class Screen ; // Screen 类的声明
class Screen ; // 声明
class StackScreen {
int topStack;
// ok: 指向一个 Screen 对象
Screen *stack;
void(*handler)();
};
只有当一个类的类体已经完整时,它才被视为已经被定义,所以一个类不能有自身类型的数据成员,但是,当一个类的类头被看到时,它就被视为已经被声明了,所以一个类可以用指向自身类型的指针或引用作为数据成员。
五、类对象
只有当定义一个类的对象时,系统才会分配存储区。
class Screen {
public:
// 成员函数
private:
string _screen;
string::size_type _cursor;
short _height;
short _width;
};
如下定义
Screen myScreen;
将分配一块足够包含 Screen 类的四个数据成员的存储区,名字 myScreen 引用到这块存储区,每个类对象都有自己的类数据成员拷贝,修改 myScreen 的数据成员不会改变任何其他Screen 对象的数据成员。
六、类成员函数
类的成员函数是一组操作的集合,用户可以在该类的对象上执行这些操作,能够在类
Screen 上执行的操作集由 Screen 类中的成员函数定义:
class Screen {
public:
void home() { _cursor = 0; }
void move(int , int);
char get() { return _screen[_cursor]; }
char get(int , int);
bool checkRange(int , int);
int height() { return _height; }
int width() { return _width; }
// ...
};
虽然每个类对象都有自己的类数据成员拷贝,但是,每个类成员函数的拷贝只有一份。例如:
Screen myScreen, groupScreen;
myScreen.home();
groupScreen.home();
当针对对象 myScreen 调用函数 home()时,在 home()中访问的成员_cursor 是对象
myScreen 的数据成员,当针对对象 groupScreen 调用 home()时,数据成员_cursor 引用的是对象 groupScreen 的数据成员,但是,两者调用的是同一个函数 home() 同一个成员函数怎样能引用两个不同类对象的数据成员呢?这种支持是通过 this 指针实现的。
七、inline(内联)
在类内部的公有部分定义的成员函数都是内联的。
通常,在类体外定义的成员函数不是 inline 的,但是,这样的函数也可以被声明为inline函数,可以通过显式地在类体中出现的函数声明上使用关键字 inline 或者通过在类体外出现的函数定义上显式使用关键字,inline 或者两者都用,例如,下面的实现定义了 move()是
Screen 的一个 inline 函数:
inline void Screen::move( int r , int c)
{ // 将 _cursor 称到绝对位置
if (checkRange(r , c)) // 位置合法吗?
{
int row = (r - 1) * _width; // 行位置
_cursor = row + c - 1;
}
}
转载于:https://blog.51cto.com/mnt3918290/1753203