C++ primer第二次阅读学习笔记(第12章:类)

长平狐 发布于 2012/10/08 15:17
阅读 49
收藏 0

第十二章:类

类的成员可以是数据、函数或类型别名。

在类内部声明成员函数是必须的,但是可以不在类内定义。在类内部定义的函数默认为inline。也就是说,当它们被调用时,编译器将试图在同一行内扩展该函数。也可以显式的将成员函数声明为inline。在声明处和定义处指定inline均可。

const加在形参列表后,就可以将成员函数声明为常量,它不能改变其所操作的对象的数据成员,同时const必须出现在成员函数的声明和定义中。若只出现一处将会导致语法错误。

类背后蕴含的的思想是:数据抽象和封装。数据抽象是一种依赖于接口和实现分离的编程。封装是将低层次的元素组合起来形成新的高层次实体的技术。函数是封装的一种形式,函数所执行的细节行为被封装在函数本身这个更大的实体中。同样的,类是一个封装的实体,它代表若干成员的聚集。

访问标号实施抽象和封装。

除了定义数据和函数成员之外,类还可以定义自己局部的类型名字。类定义的类型名与数据和函数成员一样,遵循标准访问控制。

class A

{

  public:

    typedef string::size_type index;

    index change();
    };

在类内定义的类型,在类外使用时要使用作用域操作符来访问。如A::index a;在类内则可以直接使用。

如果成员函数在类的定义体以外定义,则用于返回类型的名字在类作用域之外,如果返回类型使用类定义的类型,则必须使用完全限定名。

如  A::index A::change(){ /*操作*/};

在类内定义的类型需要在使用之前定义哦。编译器按照成员在类中出现的次序来处理它们。

如果仅仅声明了类,还没有定义。这时编译器知道其为一个类,但是不知道包含哪些成员,被称为不完全类。只能用于定义指向该类型的指针和引用,或者用于声明使用该类型作为形参类型或返回类型的函数。

一旦定义了类就可以定义该类型的对象,定义对象时,将为其分配存储空间,但定义类型时不进行存储分配。

定义类对象时有两种方式:

1A a;

2:class A a;

第二种方法是从C继承而来。

类定义以分号结束,分号是必须的,因为在类定义之后可以接一个对象定义列表。就像结构体一样。如

class A{} a1,a2;

在普通的非const成员函数中,this类型是一个指向类类型的const指针,可以改变this所指向的值,但不能改变this所保存的地址。在const成员函数中,this的类型时一个指向const类类型的const指针。既不能改变this所指的对象,也不能改变this所保存的地址。因此const成员函数只能返回*this作为const的引用。

const对象只能调const成员变量,而非const对象可以使用任何成员。

可以在类内定义mutable可变数据成员。可变成员永远都不能为const,即不能同时将成员变量指定mutableconst类型。即使对象是const时也是如此。。const成员函数可以改变mutable成员。要将成员声明为可变的,必须将关键字mutable放在成员声明之前,如:

class A

{

   public:

     mutable size_t num;

     void changeNum()const

     {

         num++;

      }
    };

被屏蔽的全局对象可以使用全局作用域操作符来引用。如::globleVariable

类成员声明的名字查找方式为:

1:检查出现在名字使用之前的类成员声明。

2:如查找不成功,则检查包含类定义的作用域中出现的声明以及出现在类定义之前的声明。

类成员函数定义中的名字查找:

1:检查成员函数局部声明。

2:如找不到,则检查对所有类成员的声明。

3:如在类中找不到,则检查此成员函数定义之前的作用域中出现的声明。

没有默认构造函数的类类型的成员、const或引用类型的成员都必须在构造函数初始化列表中进行初始化。初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。

成员初始化的次序依赖于定义的次序。而不是在初始化列表的次序。

一个类一旦定义了一个构造函数,编译器就不会在生成默认构造函数。当没有定义构造函数时才自动生成一个默认构造函数。

合成的默认构造函数会调用类类型的默认构造函数。内置和复合类型的成员,只对定义在全局作用域的对象才初始化。因此如果类中存在内置或复合类型的成员,则类不应该依赖于合成的默认构造函数,它应该定义自己的构造函数来初始化这些成员。

可以用单参构造函数定义从一个形参类型到类类型的隐式转换。

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

class A

{

  public:

  explicit A(string&);

};

只能在类内部构造函数的声明时使用explicit,不能再在类外构造函数实现时将其声明为explicit.

如果单参构造函数被声明为explicit,那么它不能执行隐式转换,此时可以显式的用构造函数来生成转换。string s("hello world!");a=A(s);    与结构体类似,可以使用显式初始化来初始化类的成员。用处不大,知道即可。此处不再详细介绍。

友元机制允许一个类将对其非公有成员的访问权限授予指定的函数或类。友元只能在类内授予,而不能在类外索取。而且它们不受访问控制的影响。

友元可以是普通的非成员函数,也可以是其他类的成员函数,或整个类。当将一个类设为友元,友元类的所有成员函数都可以访问该类。如果将一个类的成员函数设为类的友元,只有该成员函数能够访问,而且成员函数名必须用该函数所属的类的名字加以限定。

友元函数可以在授权的类内定义。但是该函数仍属于外部作用域。

必须将重载函数集中每一个希望设为友元的函数都声明为友元。

static成员函数没有this形参,它独立于该类的任意对象而存在。static成员函数和成员变量可以通过作用域操作符调用也可以通过对象、引用或指向该类类型的对象的指针间接调用。

如:

A::s;  a.s; p->s

static成员函数没有this指针,因此在该成员函数内不能引用类的普通成员。它不是任何对象的一部分,不能被声明为const,也不能被声明为虚函数。但它可以访问static成员变量。

static数据成员必须在类定义体外部定义有且仅有一次。它不能通过构造函数初始化,不能在类定义体内初始化。而是在类定义体外定义时初始化。static关键字只能用于类定义体内部的声明中,定义时不能标示static

const static数据成员是一个常量表达式,它可以再类的定义体中进行初始化。

static数据成员的类型可以是该类的类型。


原文链接:http://blog.csdn.net/ithzhang/article/details/7593872
加载中
返回顶部
顶部