最近有点烦有点烦,还是学习使我快乐,嗯,学习使我快乐~
1. 过程性编程和面向对象编程
过程性编程:首先考虑要遵循的步骤,然后考虑如何表示这些数据。
面向对象编程:首先考虑数据(如何表示数据和如何使用数据),然后使用新的设计方案创建出程序。
2. 抽象和类
2.1 类规范
- 类声明:以数据成员的方式描述数据部分,以成员函数(方法)的方式描述公有接口。放在头文件中
- 类方法定义:描述如何实现类成员函数。放在源代码文件中
- public:使用类对象的程序可以直接访问公有成员
- private:默认类型,只能通过公有成员函数(或者友元函数)访问对象的私有成员
- protected
结构具有与类相同的特性,它们唯一的区别是结构的默认访问类型是public,类的默认访问类型是private。但通常使用类实现类描述,结构只用来表示纯粹的数据对象。
2.4 实现类成员函数
- 定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类
- 类方法可以访问类的private组件
#include
#include "stock.h"
void Stock::acquire()
{
...
}
- 其定义位于类声明中的函数都将自动成为内联函数
- 也可在类声明之外定义成员函数,使用inline限定符,使其成为内联函数。放在头文件中。
//stock.h
class Stock{
private:
...
double total_val;
void set_slot(){total_val = 0;}
public:
void update(double val);
...
};
inline Stock::updte(double val)
{
total_val = val;
}
2.6 方法使用哪个对象
使用成员运算符。
每个对象都有自己的存储空间,用于存储其内部变量和类成员,但同一个类的所有对象共享同一组类方法,即每种方法只有一个副本。
Stock kate,joe;
kate.show();
joe.show();
3. 类的构造函数和析构函数
3.1 声明和定义构造函数
- 构造函数没有返回类型,位于类声明的共有部分,名称与类名称相同
- 程序声明对象时,将自动调用构造函数
- 一般在类成员变量的名称前加m_或者在后面加_后缀,以与构造函数的参数区分
- 分为显式调用和隐式调用,用new动态分配内存时也调用构造函数。
- 构造函数被用来创建对象,而不能通过对象调用。
Stock food = Stock("World",250,1.2);
Stock garment("Furry",200,2.1);
Stock * pstock = new Stock("Amy",450,2.2);
- 当且仅当没有定义任何构造函数时,编辑器才会提供默认构造函数。
- 为类定义了构造函数后,程序员就必须为类提供默认构造函数。
- 给已有构造函数的所有参数提供默认值
- 定义一个没有参数的构造函数
Stock(const String & co = "error",int n = 0,double pr = 0.0);
Stock();
使用默认构造函数:
Stock first;
Stock second = Stock();
Stock *prelist = new Stock;
- 对象过期时,编译器自动调用析构函数,不需要显示调用析构函数。
- 如果程序员没有提供析构函数,则编译器隐式地声明一个默认的析构函数。
- 析构函数为类名前加~,没有参数,可以没有返回值和声明类型。
- 如果构造函数使用了new,则必须提供使用delete的析构函数。
如果既可以通过初始化,也可以通过赋值来设置对象的值,则应采用初始化的方式,通常这种方式效率更高。因为赋值的方式会先创建临时变量,再将临时变量的值赋给变量,最后删除临时变量。
Stock stock1 = Stock("Buff",2,2.0);
Stock stock2;
stock2 = Stock("Nifty",3,3.0);
列表初始化是C++11的特性,也可用于对象初始化。
Stock hot_tip = {"Ded",4,4.0};
3.7 const成员函数
- 不会修改调用对象的成员函数为const成员函数
- 只要类方法不修改调用对象,都应将其声明为const。
class Stock{
...
public:
void show() const;
}
void Stock::show() const{
...
}
4. this指针
每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象。
const Stock & Stock::toptal::(const Stock & s) const{
if(s.total_val > total_val)
return s;
else
return *this;
}
5. 类作用域
类中定义的名称的作用域为整个类,在类声明或成员函数定义时可以使用未修饰的成员名称(未限定的名称),其它情况使用类成员名称时,要使用直接成员运算符(.)、间接成员运算符(->)或者作用域解析符(::)。
5.1 作用域为类的常量
有两种方法可以实现作用域为类的常量:
- 在类中声明一个没有变量名的枚举,用枚举为整形常量提供作用域为整个类的符号名称。用这种方法创建的枚举并不会创建类数据成员,也就是说所有对象都不包含枚举。另外,下例中的 Moths只是一个符号名称,在作用域为整个类的代码中遇到它时,编译器将用30替换它。
class Bakery{
private:
enum {Moths = 30};
double costs[Moths];
...
}
- 使用关键字static,该变量与其它静态变量存储在一起,而不是存储在对象中。因此只有一个该常量,被所有对象共享。
static const int Moths = 30;
- 传统枚举的问题:两个枚举定义中的枚举量可能发生冲突
enum egg {Small, Medium, Large, Jumbo};
enum t_shirt {Small, Medium, Large, Xlarge};
- C++11提供的作用域为类的枚举量避免了这种冲突,使用关键字class或者struct。要使用枚举名限定枚举量。
enum class egg {Small,Medium,Large,Jumbo};
enum class t_shirt {Small,Medium,Large,Xlarge};
egg choice = egg::Large;
t_shirt Floyd = t_shirt::Large;
- 在有些情况下,常规枚举将自动转化为整形,如将其赋给int变量或者用于比较表达式时,但作用域内枚举不能隐式地转换为整形,但可进行显示类型转换。
enum egg {Small,Medium,Large};
enum class t_shirt {Small,Medium,Large,Xlarge};
egg one = Medium;
t_shirt rolf = t_shirt::Large;
int king = one; //allowed
int ring = rolf; // not allowed
if(king < Large) //allowed
cout <
- 枚举用某种底层整形类型表示,在C++98中,如何选择取决于实现。在C++11中,作用域内枚举的底层类型默认为int,而且可以由程序代码指定;常规枚举的底层类型随实现而异,也可以指定。
enum class : short pizza {Small,Medium,Large};
6. 抽象数据类型
类概念非常适合与抽象数据类型。