低调、勤奋。
分类: C/C++
2013-01-13 11:01:51
终于学习到了类了,不容易。
12.1 类的定义和声明
类:就是定义了一个新的类型和一个新作用域。
类成员:每个类可以没有成员,也可以定义多个成员,成员可以是数据、函数、类型别名。
构造函数:创建一个类类型的对象时,编译器会自动使用一个构造函数来初始化该对象。
构造函数一般就使用一个构造函数初始化列表来初始化对象的数据成员。
如:Sales_item():units_sold(0),revenus(0,0) {} //位于冒号和大括号之间
成员函数:在类内部,定义的函数默认为inline。
将关键字const加在形参表后,就可以将成员函数声明为常量:
double avg_price() const;
const成员不能改变其所操作的对象的数据成员。const必须同时出现在声明和定义中,否则
会出现编译器报错。
习题:有class关键字定义的类用struct定义的类有什么不同。
答:区别在于默认的访问标号不同,如果类中某成员的定义之前没有出现任何标号,则在class中,该成员默认为private成员,在struct中为public成员。
定义重载成员函数
举例:两个重载成员中,一个版本返回由当前光标指示的字符,另一个返回指定行列处的字符。
class Screen{
public:
typedef std::string::size_type index;
char get() const { return contents[cursor]; }
char get(index ht, index wd) consts;
private:
std::string contents
index cursor;
index height, width;
}
类中定义内联函数,如果是在类中定义的,默认为内联函数,如果不在定中定义,则可在函数外部显示指定为内联函数,在类中只需要声明,不用在类中再指定为inline,这样可方便阅读。
习题:修改本节中给出的Screen类,给出一个构造函数,根据屏幕的高度,宽度和内容的值来创建Screen.
解答:
在Screen类的定义体中public部分增加如下构造函数的声明:
Screen(index hight, index wdth, const std::string &contents);
在该类的定义体之外增加如下构造函数的定义:
Screen::Screen(index hight, index wdth, const std::string &contents): contents(contents),cursor(0),height(hght),width(wdth) {}
类的定义以分号结束。
12.2 隐含的this指针
this指针:即指向该类对象的一个指针。
何时使用this指针
当我们需要将一个对象作为整体引用而不是引用对象的一个成员时,最常见的情况
是这样的函数中使用this指针,该函数返回对调用该函数的对象的引用。
例如:我们需要一个set操作,用于将光标移动到指定位置,然后通过move操作
将光标移动到新的位置。通常用户想如下操作:
myScreen.move(4,0).set('#');
这个语句等价于:
myScreen.move(4,0);
myScreen.set('#');
返回*this
如:
class Screen{
public:
Screen& move(index r, index c);
Screen& set(char);
Screen& set(index, index, char)p;
};
每个函数都返回调用自己的那个对象。使用this指针来访问该对象。
Screen& Screen::set(char)
{
contents[cursor] = c;
return *this;
}
注意:从const成员函数返回*this。
在普通的非const成员函数中,this的类型是一个指向类类型的const指针。
可以改变this所指向的值,但不能改变this所保存的地址。在const成员函数
中,this的类型是一个指向const类类型对象的const指针。既不能改变this
所指向的对象,也不能改变this所保存的地址。
即前者可以改变指针所指向的地址的值,但不能改变指向的地址。后者均不能。
基于const的重载
基于成员函数是否为const可以重载一个成员函数。
12.4 构造函数
构造函数的工作是保证每个对象的数据成员具有合适的初值。构造函数的名字与类的名字相同,并且不能
指定返回类型。构造函数不能声明为const。
建议:使用构造函数初始化列表
在许多类中,初始化和赋值严格来讲都是低效率的,数据成员可能已经被直接初始化了,还要对其进行初始化。必须对任何const或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化。
成员初始化次序:成员被初始化的次序就是定义成员的次序,注意这里不是初始化列表的顺序。
类通常应定义一个默认的构造函数:
如果类定义了自己的构造函数,则编译器不会再自动生成默认的构造函数,这往往会产生很多问题。
当构造函数被声明为explicit时,编译器将不使用它作为转换操作符。
通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为explicit。
友元:允许一个类将其对非公有成员的访问权授予指定的函数或类。
12.6 static类成员
static类成员不是任意对象的组成部分,但由该类的全体对象所共享。
习题:下面的static数据成员声明和定义中哪些是错误的。
//example.h
class Example{
public:
static double rate = 0.5;
static const int vecSize = 20;
static vector
};
//example.c
#include "example.h"
double Example::rate;
vector
解答:类的定义体中对static成员rate和vec的初始化是错误的。因为非const成员的初始化必须放在类定义体的外部。example.c文件中对static成员rate和vec的定义也是错误的,因为此处必须给出初值。