C++类

C++程序设计允许程序员使用类（class）定义特定程序中的数据类型。这些数据类型的实例被称为对象，这些实例可以包含程序员定义的成员变量、常量、成员函数，以及重载的运算符。语法上，类似C中结构体（struct）的扩展，C中结构体不能包含函数以及重载的运算符。

C 结构体与C++ 类的对比

在 C++ 中，结构体 是由关键词struct 定义的一种数据类型。他的成员和基类默认为公有的（public）。由关键词class 定义的成员和基类默认为私有的（private）。这是C++中结构体和类仅有的区别。

聚合类

聚合类是一种没有用户定义的构造函数，没有私有（private）和保护（protected）非静态数据成员，没有基类，没有虚函数。这样的类可以由封闭的大括号用逗号分隔开初始化列表。下列的代码在C 和 C++ 具有相同的语法：
struct C{
  int a;
  double b;};struct D{
  int a; 
  double b;
  C c;};// initialize an object of type C with an initializer-listC c = { 1, 2 };// D has a sub-aggregate of type C. In such cases initializer-clauses can be nestedD d = { 10, 20, { 1, 2 } };

POD 结构

一个POD结构（普通旧式数据结构）是一个不包含非POD结构、非POD联合（或者这些类型的数组）或引用的非静态成员变量（静态成员没有限制），并且没有用户定义的赋值运算符和析构器的聚合类。 一个POD结构可以说是C struct在C++中的等价物。在大多数情况下，一个POD结构拥有和一个在C中声明的对应的结构相同的内存布局。因此，POD结构有时不正式地被称为“C风格结构”（C-style struct）。

声明和使用

C++ 的结构体和类具有他们自己的成员。这些成员包括变量（包括其他结构体和类），被看做方法的函数（特定的标示符或重载的运算符），构造函数以及析构函数。成员被声明成为公共或私有使用说明符public:和private:来区分。说明符后出现的任何成员会获得相应的访问权限直到下一个说明符的出现。对于继承的类能够使用protected:说明符。

成员函数

成员函数是C++ 的类和结构体的一个重要特性。这些数据类型可以包含作为其成员的函数。成员函数分为静态成员函数与非静态成员函数。静态成员函数只能访问该数据类型的对象的静态成员。而非静态成员函数能够访问对象的所有成员。在非静态成员函数的函数体内，关键词this指向了调用该函数的对象。这通常是通过thiscall调用协议，将对象的地址作为隐含的第一个参数传递给成员函数。再次以之前的person类型作为例子：
class person{
  std::string name;
  int age;public:
  person() : age(5) { }
  void print() const;};void person::print() const{
  cout << name << ";" << this->age << endl;
  /* "name"和"age"是成员变量。     "this"关键字的值是被调用对象的地址。其类型为     const person*，原因是该函数被声明为const。  */}
在上面的例子中print()函数在类中声明，并在类的名称后加上::来限定它后加以定义。name和age是私有的（类的默认修饰符），print()被声明为公有，由于一个被用于类外的成员需要被申明为公有的。
通过使用成员函数print()，输出可以被简化为：
a.print();b.print();
上述的a和b被称为调用者（sender），当print()函数被执行时每一个都引用自己的成员变量。
将类或结构的申明（称做接口）和定义（称作实现）放入分开的单元是常见的做法。用户需要的接口被放入一个头文件中而实现则独立地放入源代码或者编译后的形式。
非静态成员函数，可以用const或volatile关键词限定。const限定的成员函数不能修改其他数据成员（除了具有mutable的例外），也不能调用非const限定的其他成员函数。编译实现时，通常是在const限定的成员函数体内，this所指向的数据成员自动具有const限定，因此是只读的。const对象只能调用const成员函数；volatile对象只能调用volatile限定的成员函数。反之，没有受到限定的普通对象可以调用所有的成员函数，不论它是否为cv限定。构造函数、析构函数不能cv限定。

继承

非POD类的内存布局没有被C++标准规定。例如，许多流行的C++编译器通过将父类的字段和子类的字段并置来实现单继承，但是这并不被标准所需求。这种布局的选择使得将父类的指针指向子类的操作是平凡的（trivial）。
例如，考虑：
class P 
{
    int x;};
class C : public P 
{
    int y;};
一个P的实例和P* p指向它，在内存中可能看起来像这样：
+----+
|P::x|
+----+
↑
p
一个C的实例和P* p指向它，在内存中可能看起来像这样：
+----+----+
|P::x|C::y|
+----+----+
↑
p
因此，任何操纵P对象的字段的代码都可以操纵在C对象中的P字段而不需要考虑任何关于C字段的定义。一个正确书写的C++程序在任何情况下都不应该对被继承字段的布局有任何假定。使用static_cast或者dynamic_cast类型转换运算符会确保指针正确的从一个类型转换为另一个。
多重继承并不那么简单。如果一个类D继承了P1和P2，那么两个父类的字段需要被按照某种顺序存储，但是（在大多数情况下）只有一个父类可以被放在子类的头部。每当编译器需要将一个指向D的指针转换为P1或P2中的任一个，编译器需要提供一个自动转换从子类的地址转换为父类字段的地址（典型地，这是一个简单的偏移量计算）。
关于多重继承的更多信息，参看虚继承。

重载运算符

C++容许程序员重载某些运算符，目的是补充库中未能提供的针对特定类的运算符。同理，很多时自定类也因为内置库不能提供指定运算符而需要重载。
另外，当程序员没有重载或定义某些运算符时，编译器会自动地创建它们，例如三法则中的复制指定运算符（=）。
依照惯例，重载运算符时应模拟运算符本身意义的功能，例如重载运算符“*”时，程序员义务重载为两数之乘法（或其他，视数学或程序上的意义）。另外，宣告一结构如integer类，当重载运算符如“*”就要回传integer类：
struct integer 
{
    int i;
    integer(int j = 0) : i(j) {}
    integer operator*(const integer &k) const 
    {
        return integer (i * k.i);
    }};
或
struct integer 
{
    int i;
   
    integer(int j = 0) : i(j) {}
 
    integer operator*(const integer &k) const;};
 
integer integer::operator*(const integer &k) const 
{
    return integer(i * k.i);}
在这里，const关键字出现两次。表达式const integer &k中的const关键字代表函数不能修改此常量值，而第二个const关键字代表此函数不会修改类对象本身（*this）。
而integer &k之中，符号（&）表示以引用形式调用。当调用函数时会直接传递变量地址，并以变量本身取代这里的变量k。

构造函数

有时软件工程师会想要他们的变量在声明时有一个默认值。这可以通过声明构造函数做到。
person(string N, int A) 
{
    name = N;
    age = A;}
成员变量可以像下面的例子一样，利用一个冒号，通过一个初始化序列初始化。这与上面不同，它进行了初始化（使用构造函数），而不是使用赋值运算符。这对类类型来说更有效，因为它只需要直接构造；而赋值时，它们必须先使用默认构造函数进行第一次初始化，然后再赋予一个不同的值。而且一些类型（例如引用和const类型）不能被赋值，因而必须通过初始化序列进行初始化。
person(std::string N, int A) : name(N), age(A) {}
注意花括号不能被省略，即使为里面为空。
默认值可以给予最后的几个参数类帮助初始化默认值。
person(std::string N = "", int A = 0) : name(N), age(A) {}
在上面的例子中，当没有参数给予构造函数时，等价于调用以下的无参构造函数（一个默认构造函数）：
person() : name(""), age(0) {}
构造函数的声明看起来像一个名字和数据类型相同的函数。事实上，我们的确可以用函数调用的形式调用构造函数。在这种情况下一个person类型的变量会成为返回值：
int main() 
{
    person r = person("Wales", 40);
    r.print();}
以上的例子创建了一个临时的person对象，然后使用复制构造函数将其赋予r。一个更好的创建对象的方式（没有不需要的拷贝）：
int main() 
{
    person r ("Wales", 40);
    r.print ();}
具体的程序行为，可以也可以不和变量有关系，可以被作为一部分加入构造函数。
person() 
{
    std::cout << "Hello!" << endl;}
通过以上的构造函数，当一个person变量没有被具体的值初始化时，“Hello!”会被打印。

默认构造函数

当类没有定义构造函数时，默认构造函数将被调用。
class A { int b;};//使用括号创建对象A *a = new A(); //调用默认构造函数，b会被初始化为'0'//不使用括号创建对象A *a = new A; //仅分配内存，不调用默认构造函数，b会有一个未知值
然而如果用户定义了这个类的构造函数，两个声明都会调用用户定义的构造函数。而在用户定义的构造函数中的代码会被执行，并且不会赋予b默认值。

析构函数

一个析构函数是一个构造函数的逆，当一个类的一个实例被销毁时会被调用，例如当一个类在块（一组花括号“{}”)中被构造的一个对象会在关闭括号后删除，之后析构函数被自动调用。它会在清空保存变量的内存位置时被调用。析构函数可以在类被销毁时用来释放资源，例如堆分配的内存和打开的文件。
声明一个析构函数的符号类似于构造函数。它没有返回值而且方法的名称和在类的名称前加上波浪线（~）相同。
~person() 
{
    cout << "I'm deleting " << name << " with age " << age << endl;}
另外要注意的是，析构函数是不容许参数传递。然而，与构造函数一样，析构函数可以被显式调用：
int main() 
{
    person someone("Wales", 40);
    someone.~person();  //此時會輸出一次"I'm deleting Wales with age 40"

    return 0;  //第二次輸出"I'm deleting  with age 40"}/* 在這裡，程式結束時會自動調用析構函數，   而person.name在第一次調用析構函數時已被清除，   但person.age會按編譯器而定，   沒能在第一次調用析構函數時清零。 */

类模板

类模板，是对一批仅仅成员数据类型不同的类的抽象，程序员只要为这一批类所组成的整个类家族创建一个类模板，给出一套程序代码，就可以用来生成多种具体的类，这类可以看作是类模板的实例，从而大大提高编程的效率。

属性

C++语法试图使一个结构的所有方面看起来像一个基本数据类型。因此，运算符重载允许结构像整数和浮点数一样操作，结构的数组可以通过方括号声明（some_structure variable_name[size]），而且指向结构的指针可以通过和指向内置类型的指针通用的方法解引用。

内存消耗

结构的内存消耗至少是组成变量的内存大小的总和。参考如下twonums 结构例子。
struct twonums 
{
    int a;
    int b;};
这个结构包含两个整型。在当前许多C++ 编译器中，整型默认是32 位整型， 所以每个成员变量消耗4 个字节的内存．因而整个结构至少（或者正好）消耗 8 个字节的内存，见下图。
+----+----+
| a  | b  |
+----+----+
然而，编译器可能在变量或者结构的结尾添加空的位， 这样可以保证和给定的计算机结构匹配，通常是把变量添加到32 位。如下例子所示的结构:
struct bytes_and_such{ 
   char c;
   char C;
   short int s;
   int i;
   double d;};
可看成
+-+-+--+--+--+--+--------+
|c|C|XX|s |  i  |   d    |
+-+-+--+--+--+--+--------+
在内存中, XX 表示两个未被使用的空比特。
因为结构可能会使用指针和数组去声明 或者初始化变量，结构的内存消耗不一定是固定的。另外一个内存消耗不固定的例子是模板结构。

位字段

位字段（Bit field）可以被用来定义比内置类型还要小的类成员变量。通过这个字段定义的变量，只可以像使用内置的整数类型(例如int, char, short, long...)那样子使用。
struct A{ 
unsigned a:2; // 可以存储0-3的数字，占据一个int前2 bit的空间.
unsigned b:3; // 可以存储0-7的数字，占据之后3 bit的空间.
unsigned :0;  // 移动到下一个内置类型的末尾
unsigned c:2; 
unsigned :4;  // 在c和d中间加4bit的空白
unsigned d:1;
unsigned e:3;};// 内存结构/*4 byte int   4 byte int[1][2][3][4] [5][6][7][8][1]                   [2]              [3]              [4][a][a][b][b][b][][][] [][][][][][][][] [][][][][][][][] [][][][][][][][][5]                  [6]                [7]              [8][c][c][][][][][d][e] [e][e][][][][][][] [][][][][][][][] [][][][][][][][]*/
位字段不能在结构体中使用，它只能在使用struct或者class关键字定义的类中使用。

this关键字

complex& operator+=(const complex & c) 
{
    realPart += c.realPart;
    imagPart += c.imagPart;
    return *this;}