对象和类
抽象和类
类是一种将抽象转换为用户定义类型的C++工具,他讲数据表示和操纵数据的方法组合成一个整洁的包
类规范:
- 类声明:以数据成员的方式描述数据部分,一成员函数的方式描述公有接口。
- 类方法定义: 描述如何实现类成员的接口。
控制访问:
关键字 private 和 pubilc 和 protected.
只能通过公有成员函数(或友元函数)来访问对象的私有成员。将实现希捷放在一起并将他们与抽象分开被称为封装。数据隐藏是一个种封装。封装的另一个例子是,将函数定义和类声明放在不同的文件中。
- private:
有该关键字的成员只能通过公共成员访问(数据隐藏) - public:
该表示组成类的公共接口的类成员(抽象) - 成员可以是数据也可以是函数。
不必在类声明中使用关键字private,因为这是类对象的默认访问控制。
- 定义成员函数时,使用作用域解析运算符(::)来表示函数所属的类。
- 类方法可以访问类的private组件。
内联方法:
其定义位于类声明中的函数都将自动称为内联函数。如果愿意,也可以在类声明之外定义成员函数,并使其成为内联函数。为此,只需要在类实现部分中定义函数时加上inline限定符即可。
在类声明中定义方法和上述方式定义方法(使用inline)是等价的。
使用对象:
class Stock{
...
};
Stock kate,joe;
kate.show();
在kate.show()函数中,使用的类成员shares会被解释称kate.shares.
所创建的每个新对象都有自己的存储空间,用于存储器内部变量和类成员。但同一个类的所有对象共享同一组方法,即每种方法只有一个副本。
使用类
创建类:声明类变量,使用new为类对象分配存储空间。
类的构造函数和析构函数
类可以像结构一个初始化,前提是数据是public的
声明和定义构造函数:
构造函数的名称和类名相同,构造函数的原形和函数头没有返回值。(构造函数没有声明类型)
如果在类定义中有如下原形:
class Stock{
public:
Stock(const string & co, long n = 0, double pr = 0.0); //参数名不能与类成员相同。
...
}
为了避免参数名混乱,可以在类参数前面使用m_的前缀,或者在最后使用_的后缀。(可以把构造函数定义为private)
使用构造函数:
C++有两种使用构造函数来初始化对象的方式,第一种方式是显式地调用构造函数:
```c++
Stock food = Stock("World Cabage", 250, 1.25);
另一种方式是隐式地调用构造函数:
Stock garment("Furry Mason", 50, 2.5);
这两种构造方式是等价的。
下面是使用new创建类对象:
Stock *pstock = new Stock("Electroshock Games", 18, 19.0);
无法使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在的,因此构造函数被用来创建对象,而不能通过对象来调用。
默认构造函数:
默认构造函数是在未踢狗显示初始值时,即:
Stock fluffy_the_cat;
如果没有提供任何构造函数,则C++将自动提供默认的构造函数。如果提供了非默认构造函数,但是没有提供默认构造函数,则直接声明会出错。
可以通过函数重载来定义另一个构造函数————一个没有任何参数的构造函数或给所有的参数都提供默认值:
Stock();
//or:
Stock(const string & co = "Error", int n = 0, double pr = 0.0);
隐式地调用默认构造函数时,不要使用圆括号:
Stock second();
这是一个函数声明,不是对象调用构造函数。
析构函数
对象过期时,程序将自动调用一个特殊的成员函数————析构函数。
析构函数的名称很特殊:在类名前加上~。
因此Stock类的析构函数是~Stock()。
析构函数没有参数,因此Stock析构函数的原形必须是这样的:
~Stock();
析构函数可以如下定义:
Stock::~Stock(){
cout << "Bye," << endl;
}
- 析构函数的调用由编译器决定,通常不应在代码中显示调用析构函数。
- 如果是静态存储对象,则析构函数将在程序结束时自动被调用。
- 如果创建的是自动存储类对象,则析构函数将在程序执行完代码块时自动被调用。
- 如果对象是通过new创建的,当使用delete来释放内存的时候,其析构函数将自动被调用。
对于
Stock stock2 = Stock("Boffo Objects",2,2.0);
在c++标准中,允许编译器使用两种方式来执行。一种是和 stock2(“Boffo Objects”,2,2.0)一样的语法,另一种是先创建一个临时对象,然后将该临时对象复制到stock2中,并丢弃它。如果此时使用析构函数,那么在丢弃时会调用。
C++中允许:
stock1 = Stock("Nifty Foods", 10, 50.0);
创建一个新的临时对象,然后复制到已有的对象中,再把该临时对象删除。
上述两个代码块中的语句有根本性的区别。
在C++中,可将列表初始化语法用于类。只要提供与某个构造函数的参数列表匹配的内容,并用大括号将它们括起来。
例如:
Stock hot_tip = {"Derivatives Plus Plus", 100, 45.0};
Stock temp {};
const 成员对象:
使用const定义的对象,不能调用非const的成员函数,否则程序报错。
const成员函数定义方法:const关键字放在函数的括号后面。例如:
//在声明中:
void show() const;
...
//在定义中:
void stock::show() const{
...
}
如果构造函数只接受一个参数,则可以像int char变量赋值一样初始化
this指针
对象可以访问同类对象的私有成员
在一个对象中,this表示指向该对象的一个指针。在成员函数中调用成员时,都是this的缩写。例如:
a;
this->a;
对象数组
emmm
类作用域
在类中定义的名称的作用域都为整个类,类作用域以为着不能从外部直接访问类成员,公有成员函数也是如此。
要调用公有成员函数,必须通过对象。
在类声明或成员函数定义中,额昆虫直接使用未修饰的成员名称。其他情况下,必须使用直接成员运算符、间接成员运算符或作用域解析运算符。(. -> :😃
作用域为类的常量:
-
枚举
class Bakery{ private: enum {Months = 12}; double costs[Months]; ... };
使用这种方式的声明枚举并不会创建数据成员。也就是所有的对象中不包含枚举。
-
关键字static:
class Bakery{ private: static const int Months = 12; double costs[Months]; };
该变量将于其他静态变量存储在一起,而不是存储在对象中。
抽象数据类型
pass