类定义是以关键字class
开头,后面跟类的名称。主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。
类的对象的公共数据成员可以使用直接成员访问运算符.
来访问。需要注意的是,私有的成员和受保护的成员不能直接使用成员访问运算符来访问。
类成员函数
类的成员函数是指把定义和原型写在类定义内部的函数。类成员函数是类的一个成员,他可以操作类的任意对象,可以访问对象中的所有成员。
成员函数可以定义在类定义内部,或者单独使用范围解析运算符::来定义,在类定义中定义的成员函数把函数声明为内联的,即使没有使用inline
标识符。声明必须写在类的内部。
在类外定义的格式为:
数据类型 类名::方法名(参数列表) {}
类访问修饰符
数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记访问修饰符public private protected
来指定的。
一个类可以有多个访问修饰符标记区域,每个标记区域在下一个标记区域开始之前或者遇到类主体结束右括号之前都是有效的。
成员和类的默认访问修饰符是private
- 公有
public
:公有成员在程序中类的外部是可访问的。您可以不适用任何成员函数来设置和获取公有变量的值。 - 私有
private
:已有成员变量或函数在类的外部是不可访问的,甚至是不可查看的,只有类和友元函数可以访问私有成员。默认情况下,类对所有成员都是私有的。
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数。 - 保护
protected
:保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
对于一个空类,编译器默认产生4个成员函数:默认构造函数、析构函数、拷贝构造函数和赋值函数。
还有关于继承中访问权限问题:传送门
类构造函数&析构函数
类的构造函数时类的一种特殊的成员函数,他会在每次创建类的新对象时执行。
构造函数的名称与类名是完全相同的,并且不会返回任何返回类型,也不会返回void,构造函数可用于为某些成员变量设置初始值。如果需要,构造函数也可以带有参数。
当类中未定义构造函数时,编译器会自动假设存在两个默认构造函数。
类名:类名() {}
类名:类名(const 类名&a){} //没有什么用
如果自己定义了构造函数,则默认的构造函数不会存在。
构造函数可以被重载。
可以使用初始化列表来初始化字段,例如:
class C
{T X,Y,Z;C();
}
C::C(T a,T b,T c):X(a),Y(b),Z(c)
{...
}
类的析构函数是类的一种特殊的成员函数,他会在每次删除所创建的对象时执行。析构函数的名称与类对 名称是完全相同的,只是在前面加了~
作为前缀,他不会返回任何值,也不能带任何参数。
析构函数不能重载,如果没有写析构函数,C++会自动帮我们写一个析构函数。
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于
- 复制对象把它作为参数传递给函数
- 复制对象,并从函数返回这个对象
- 通过使用另一个同类型的对象来初始化新建的对象(拷贝初始化)
如果类没有定义拷贝构造函数,编译器会自行定义一个,如果类带有指针变量,并由动态分配内存,则它必须有一个拷贝构造函数(否则会引发错误)。
最常见的形式如下:
classname (const classname &obj)
{//主体
}
这里对拷贝初始化进行进一步的说明:
A x(y); //直接初始化,如果是类类型将调用构造函数
A x=y; //拷贝初始化,如果是类类型将调用拷贝构造函数
值包含类类型成员或者内置类型(不包含指针类型)成员的类无须显式地定义拷贝构造函数也可以进行拷贝。当类的成员函数包含指针或者是成员表示在构造函数中分配的其他资源时,就必须定义拷贝构造函数。
友元函数
友元函数是定义在类外部,但是有权访问类的所有私有成员和保护成员,如果不是static成员则需要对象作为参数,如果访问static成员则不需要参数的函数,尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数称为友元函数;友元可以是一个类,该类称为友元类。在这种情况下,整个类及其所有成员都是友元。如果要声明函数为一个友元函数,需要在类定义中该函数原型前使用关键字friend
.
class A
{friend 返回类型 函数名B(参数列表);
};
返回类型 B(参数列表)//请注意,A不是任何类的成员函数
{}
int main()
{A a; B(参数列表);//对友元函数的调用不需要对象和类
}
声明类B的所有成员为另一个类A的友元则需要在A的定义专用加上以下声明:
class A
{...friend class B;
}
同样在友元类中我们也可以通过对象参数访问保护和私有成员。
内联函数
内联函数通常与类一起使用,如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。对内联函数进行修改都要重新编译函数的所有客户端,因为编译器需要更换一次所有的代码。
如果想要把一个函数定义为内联函数,则需要在函数定义前面放置关键字inline
。如果已定义的函数多于十行,编译器会忽略inline
限定符。
在类定义中的函数都是内联函数,即使没有使用内联函数。
- 在内联函数内不允许使用循环语句和开关语句