学习C++.Primer.Plus 10 对象和类
1.类的声明和定义
-
类的声明和定义。
类声明的格式如下:
class className { private://private 是类对象的默认访问控制,因此,可以省略 data member delarations//类的私有数据成员名中使用m_开头是个不错的习惯 public: member function prototypes }
定义成员函数时,使用作用域解析符来标识其所属的类:
className::functionName()是函数的限定名(qualified name); 而functionName()是非限定名。 -
结构和类的区别。
结构的默认访问类型是public,而类为private,C++程序员通常使用类来实现类型描述,而把结构限制为只表示纯粹的数据对象或没有私有部分的类。 -
内联方法
在类声明中定义方法:
根据改写,这种写法等同于用原型替换方法定义,然后在类声明的后面将定义改写为内联函数。
/*头文件中*/ class Stock { private: ... void set_tot(){...}//定位位于声明中的写法 public: ... }
内联函数的特殊性要求在每个使用它们的文件中都对其进行定义。最简便的方法就是把内联定义放在定义类的头文件中:
/*头文件中*/ class Stock { private: ... void set_tot();//声明和定义分开的写法 public: ... } inline void Stock::set_tot() { ... }
2.构造函数和析构函数
- 声明和定义构造函数
class Stock { ... public: Stock(const char * co, int n = 0; double pr = 0.0);//构造函数没有声明类型;没有返回类型。原型位于声明的公有部分。 }
- 使用构造函数
Stock garment ("Furry Mason", 50, 20); //与下面的等价 Stock garment = Stock("Furry Mason", 50, 20);
- 默认构造函数
如果定义了构造函数,编译器就不会提供默认构造函数。
如果要创建对象而不显示初始化,就必需提供默认构造函数。给已有构造函数全部提供默认值 或 提供没有参数的构造函数。 - 析构函数
像构造函数一样,析构函数也可以没有返回值和声明类型。与构造函数不同的是,析构函数没有参数。如果没提供析构函数,编译器会隐式声明一个析构函数。
用new创建的对象在delete时会自动调用析构函数。
Stock ~Stock() { ... }
- 编译器初始化类对象有可能使用以下两种方法中的一种:
Stock stock2 = Stock("Boffo Objects", 2, 2.0);
1.使其与Stock stock1("Boffo Objects", 2, 2.0)完全相同,直接创建对象并初始化为指定的值
2.调用构造函数创建一个临时对象,然后将其复制到stock2中,并丢弃该临时对象。 - 给类对象赋值时,总分使用上面的第二种方法,用构造函数创建一个临时对象,然后将其复制到stock2中,再调用析构函数删除。
Stock stock2; stock2 = Stock("Nifty Foods", 10, 50.0);
-
自动变量存储在堆栈中,因此最后创建的对象将最先被删除。
int main() { Stock stock1;// Stock stock2;//最先被析构 return 0; }
-
const成员函数。只要函数不修改调用对象时,应尽量把函数声明为const类型。
//声明: void show()const; //定义: void Stock::show()const { ... }
因为const类型的对象在调用非const成员函数时将拒绝执行。
const Stock land = new Stock("Kludgehorn"); land.show();//这里如果不是const函数,编译器将拒绝执行。
-
接受一个参数的构造函数允许使用赋值语法来将对象初始化为一个值。
//构造函数原型 Stock(int n); //那么可以这么初始化对象: Stock stock2 = 39;
3.this指针
- 所有成员方法(包括构造函数和析构函数)都将this指针设置为 调用它的对象的地址,要引用整个对象,可以使用解除引用符号:*this。
4.对象数组
- 创建对象数组:
Stock stocks[10] = { Stock ("Naruto", 12, 43.0), Stock(), Stock("Saski") };
初始化对象数组的方案是:首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后将临时对象的内容复制到相应的数组元素中。因此,要创建类对象数组,则这个类必须有默认构造函数。
5.类作用域
- 使用关键字static可以在类中定义常量,该常量将与其它静态变量存储在一起,而不是存储在对象中。因此只有一个,它被所有类对象共享。
class Stock { private: static const int Len = 30; ... }
- 在类中定义不会创建类数据成员的枚举。
class Stock { private: enum {Len = 30 }; ... }
上面的Stock类中,所有对象中都不包含枚举。另外,Len只是一个符号名称,在作用域为整个类的代码中遇到它时,编译器将用30来替换它。
附:
- cout 和 cerr 的区别
在Windows操作系统中,操作系统的重定向只影响cout而不影响cerr。如不特意指定,cout和cerr均指向屏幕。
/*fileName=test.cpp*/ void main() { cout << "cout"; cerr << "cerr"; }
在控制台运行test.exe >D:\test.txt时,操作系统重定向输出流到D:\test.txt,此时cout会输出到该文件,而cerr依旧会输出到屏幕。