C++ Primer 类

来源:互联网 发布:矩阵的qr分解 编辑:程序博客网 时间:2024/06/05 16:53

类:

 

关键字const

const加在形参列表之后,就可以将成员函数声明为常量。如double avg_price() const; const成员不能改变其所操作的对象的数据成员,const必须同时出现在声明和定义中,若只出现在其中一处,就会出现一个编译错误。

使用类型别名来简化类:

class Screen {

     public:

         // interface member functions

     private:

         std::string contents;

         std::string::size_type cursor;

         std::string::size_type height, width;

     };

class Screen {

     public:

         // interface member functions

         typedef std::string::size_type index;

     private:

         std::string contents;

         index cursor;

 553

         index height, width;

     };

所定义的类型名遵循任何其他成员的标准访问控制。将 index的定义放在类的 public 部分,是因为希望用户使用这个名字。Screen类的使用者不必了解用 string 实现的底层细节。定义 index来隐藏 Screen 的实现细节。

类成员函数的重载:

成员函数只能重载本类的其他成员函数。类的成员函数与普通的非成员函数以及在其他类中声明的函数不相关,也不能重载它们。重载的成员函数和普通函数应用相同的规则:两个

重载成员的形参数量和类型不能完全相同。调用非成员重载函数所用到的函数匹配(第 7.8.2节)过程也应用于重载成员函数的调用。

内联函数:

在类内部定义的成员函数将自动作为inline处理。

在声明和定义处指定 inline都是合法的。

何时使用 this指针:

尽管在成员函数内部显式引用 this通常是不必要的,但有一种情况下必须

这样做:当我们需要将一个对象作为整体引用而不是引用对象的一个成员时

常见的情况是在这样的函数中使用 this:该函数返回对调用该函数的对象的引

用。

class Screen {

     public:

          // interface member functions

          Screen& move(index r, index c);

          Screen& set(char);

          Screen& set(index, index, char);

          // other members as before

     };

 

注意,这些函数的返回类型是 Screen&,指明该成员函数返回对其自身类类

型的对象的引用。每个函数都返回调用自己的那个对象。使用 this指针来访问

该对象。下面是对两个新成员的实现:

     Screen& Screen::set(char c)

     {

         contents[cursor] = c;

         return *this;

     }

     Screen& Screen::move(index r, index c)

     {

         index row = r * width; // row location

         cursor = row + c;

         return *this;

     }

 

在普通的非 const 成员函数中,this 的类型是一个指向类类型的 const指针(第 4.2.5 节)。可以改变 this所指向的值,但不能改变 this 所保存的地址。

构造函数:

构造函数的名字与类的名字相同,并且不能指定返回类型。像其他任何函数一样,它们可以没有形参,也可以定义多个形参。

按照与成员声明一致的次序编写构造函数初始化列表。此外尽可能避免使用成员来初始化其他成员。

可以为一个类声明的构造函数的数量没有限制,只要每个构造函数的形参表是唯一的。用于初始化一个对象的实参类型决定使用哪个构造函数。与任何其他函数一样,构造函数具有名字、形参表和函数体。与其他函数不同的是,构造函数也可以包含一个构造函数初始化列表:

     // recommended way to write constructors using a constructor

initializer

     Sales_item::Sales_item(const string &book):

          isbn(book), units_sold(0), revenue(0.0) { }

 

构造函数初始化列表以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在圆括号中的初始化式。构造函数初始化只在构造函数的定义中而不是声明中指定。

因为内置类型的成员不进行隐式初始化,所以对这些成员是进行初始化还是赋值似乎都无关紧要。除了两个例外,对非类类型的数据成员进行赋值或使用初始化式在结果和性能上都是等价的。

下面的构造函数是错误的:

     class ConstRef {

     public:

         ConstRef(int ii);

     private:

         int i;

         const int ci;

         int &ri;

     };

     // no explicit constructor initializer: error ri is uninitialized

     ConstRef::ConstRef(int ii)

     {              // assignments:

          i = ii;   // ok

          ci = ii;  // error: cannot assign to a const

          ri = i;   // assigns to ri which was not bound to an object

     }

 

记住,可以初始化 const对象或引用类型的对象,但不能对它们赋值。在开始执行构造函数的函数体之前,要完成初始化。初始化 const或引用类型数据成员的唯一机会是构造函数初始化列表中。编写该构造函数的正确方式为

     // ok: explicitly initialize reference and const members

ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }

必须对任何 const 或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化式。一般情况下,通过(重复)使用构造函数的形参而不是使用对象的数据成员,

可以避免由初始化式的执行次序而引起的任何问题。

X(int val): i(val), j(val) { }

初始化类类型的成员时,要指定实参并传递给成员类型的一个构造函数。

合成的默认构造函数(synthesized default constructor)使用与变量初始化相同的规则来初始化成员。具有类类型的成员通过运行各自的默认构造函数来进行初始化。内置和复合类型的成员,如指针和数组,只对定义在全局作用域中的对象才初始化。当对象定义在局部作用域中时,内置或复合类型的成员不进行初始化。

 如果类包含内置或复合类型的成员,则该类不应该依赖于合成的默认构造函数。它应该定义自己的构造函数来初始化这些成员

抑制由构造函数定义的隐式转换:

可以将构造函数声明为explicit来防止在需要隐式转换的上下文中使用构造函数。

explicit关键字只能用于类内部构造函数声明上,在类的定义体外部所做的定义上不再重复。

通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为 explicit。将构造函数设置为 explicit 可以避免错误,并且当转换有用时,用户可以显式地构造对象。

友元:

友元的声明以关键字friend开始,它只能出现在类定义的内部,友元声明可以出现在类中的任何地方,通常将友元声明成组的放在类定义的开始或结尾是个好主意。

Static成员:

Static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象关联。Static成员函数没有this形参,它可以直接访问所属类的static成员,但不能直接使用非static成员。

使用类的staitc成员的优点:

(1)       static成员的名字是在类的作用域中,因此可以避免与其他成员或全局对象名字冲突。

(2)       可以实施封装。Static成员可以是私有成员,而全局对象不可以。

(3)       通过阅读程序容易看出static成员是与特定类关联的,这种可见性可清晰地显示程序员的意图。

可以通过作用域运算符从类直接调用static成员,或通过对象、引用或指向该类类型对象的指针间接调用。当我们在类的外部定义static成员时,无需重复指定static保留字,该保留字只出现在类定义内部的声明处。

Static函数没有this指针。

因为static成员不是任何对象的组成部分,所以static成员函数不能拿被声明为const,毕竟,将成员函数声明为const就是承诺不会修改该函数所属对象。最后,static成员函数也不能声明为虚函数。

Static数据成员可以声明为任意类型,static数据成员必须在类定义体的外部定义(正好定义一次),不是通过构造函数进行初始化,而是应该在定义时初始化。

static 数据成员的类型可以是该成员所属的类类型。非 static成员被限定声明为其自身类对象的指针或引用:

class Bar {

     public:

         // ...

     private:

         static Bar mem1; // ok

         Bar *mem2;       // ok

         Bar mem3;        // error

     };

 

类似地,static数据成员可用作默认实参:

     class Screen {

     public:

         // bkground refers to the static member

         // declared later in the class definition

         Screen& clear(char = bkground);

     private:

         static const char bkground = '#';

     };

static数据成员不能用作默认实参,因为它的值不能独立于所属的对象

而使用。

0 0