面向对象编程(OOP)特性:
P341
类是一种将抽象转换为用户定义类型的C++工具,它将数据表示和操纵数据的方法组合成一个简洁的包。
类规范由两部分组成: 类声明提供了类的蓝图,而方法定义则提供了细节。
【注意】:声明类只是描述对象的形式,并没有创建类,在创建类之前,将没有用于存储值的空间
通常,C++程序员将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源文件中。
类设计尽可能将公有接口和实现细节分开,被称为封装。
数据隐藏(将数据放在类的私有部分)也是一种封装,将实现细节隐藏在私有部分中,也是一种封装。将类函数定义和类声明放在不同的文件中,也是封装。
从使用者的角度看,只需要知道是成员函数的功能,并不关心使用的哪种方法。原则是将实现细节从接口设计中分离出来。
【技巧1】:常见的约定------将类名的首字母大写。
【技巧2】:数据项放在私有部分,组成类接口的成员函数放在公有项。
类的默认访问类型为私有private,而结构是公有public
其定义位于类声明的函数都将自动成为内联函数。
代码如下(示例):
class Stock
{
void set_tot() //方法一:类声明中定义
{
//...
}
};
等价于
class Stock
{
void set_tot();
};
inline void Stock::set_tot() //方法二:类外内联
{
//...
}
所创建的每一个类对象都有自己的存储空间,用来存储其内部变量,但同一个类的所有对象共享同一组类方法。
在OOP中,调用成员函数被称为发送消息。
使用成员运算符句点调用类公有方法。
Stack sta; //创建对象
sta.set_tot(); //调用类方法
P352
类构造函数,专门用于构造新对象、将值赋给它们的数据成员。
class Stock
{
public:
// constructor prototype with some default arguments
Stock(const string& company, long shares = 0);
private:
std::string m_company;
long m_shares;
}
//construckor definition
Stock::Stock(const string& company, long shares)
{
m_company = company;
m_shares = shares;
}
// 构造函数初始化列表
Stock::Stock(const string& company, long shares):m_company(company), m_shares(shares){
}
在创建对象时,如果类内当且仅当没有提供任何构造函数,则C++将自动提供默认构造函数。
Stock::Stock(){
} //默认构造函数
//没有提供任意构造函数,下面创建正确
Stock stock1; //yes
//提供了非默认构造函数,下面的创建报错
Stock stock1; //no
这样做的原因可能是:想禁止创建未初始化的对象。
【注意】:通常,应初始化所有的对象,以确保所有成员一开始就有已知的合理值。
Stock first("Tom", 20); //调用有参构造函数
Stock second(); // 定义一个返回为Stock对象的函数
Stock third; //调用默认构造函数
对象结束其生命周期,系统自动执行析构函数。作用:清理善后工作
如果构造函数使用new来分配内存,则析构函数将使用delete来释放内存。如果没有使用new,析构函数没有要完成的任务。
//析构函数原型
~Stock();
//析构函数定义
Stock::~Stock(){
}
类中必须有析构函数。如果程序员没有提供析构函数,编译器将隐式地声明一个默认析构函数。并在发现导致对象被删除的代码后,提供默认析构函数的定义。
保证函数不会修改调用对象。
void show() const;
void Stock::show() const
【技巧】:只要类方法不修改调用对象,就应将其声明为const。
P363
有时候方法可能涉及到两个对象时,需要使用C++的this指针
看下面的例子:
//比较两个对象,问题在于不能返回当前对象
const Stock& topval(const Stock& s) const
{
if (s.val > val)
{
return s;
}
return ??? ;
}
//返回类型为引用意味着返回的是调用对象本身,而不是其他副本。
为了解决此问题,使用被称为this的特殊指针,this指针指向用来调用成员函数的对象。
this指针指向调用对象的地址;*this引用调用对象。
P368
用户通常要创建同一类的多个对象,创建对象数组更为合适。
创建方法
Stock mystuff[4]; //creates an array of 4 Stock objects
Stock stocks[3] = {
Stock("NanoSmart", 12.5, 20),
Stock("Boffo Objects", 200, 2.0)
};
P370
在类中定义的名称的作用域是整个类。
不可以在类中直接创建const常量。
class Stock{
const int Months = 12; // fails
}
因为声明类只是类的蓝图,在创建对象前,没有用于存储值的空间。
第一种是类中声明一个枚举
class Stock{
enum {
Months = 12}; // 枚举创建常量
int Stocks[Months]; //将常量用于数组
}
// 由于使用枚举只是为了创建符号常量,并不打算创建枚举类型的变量,因此不需要提供枚举名。
用这种方式声明枚举并不会创建类数据成员。所有对象都不包含枚举。Months只是一个符号名称,在类中遇到Months,编译器将会用12替换它。
另一种是使用关键字static
class Stock{
static const int Months = 12; // static创建整数常量
int Stocks[Months]; //将常量用于数组
}
该整数常量将与其他的静态变量存储在一起,不是存储在对象中。
【注意】:只有静态整数常量(int,char,bool),可以在类中初始化。
传统的枚举有些问题
//无法编译,位于相同的作用域,发生冲突。
enum egg{
small};
enum shirt{
small};
C++11提供了一种新枚举,其枚举作用域为类。
enum class egg{
small}; //可以编译
enum class shirt{
small};
C++98中,包含枚举结构的长度可能随系统而异。
C++11中,作用域内枚举的底层类型为int。
P373
实现stack数据类型。