文章目录
前言
本人在阅读C++ primer plus(第六版)的过程中做的笔记,写这篇文章既是为了分享,也是为了以后查阅。以下是本篇文章正式内容。
一、抽象和类
使用类对象的程序可以直接访问公有部分,但只能通过公有成员函数或友元函数来访问对象的私有成员。不必在类声明中使用关键字private,因为这是类对象的默认访问控制。其定义位于类声明中的函数都将自动称为内联函数,类声明通常将短小的函数作为内联函数。如果愿意,可以在类声明之外定义内联函数,只需在类实现部分中定义函数时使用关键字inline即可:
class Stock
{
private:
……
void set_tot();
public:
……
}
inline void Stock::set_tot()
{
……
}
内联函数的特殊规则要求每个使用内联函数的文件都要对其进行定义,确保内联函数对多文件程序的所有文件都可用、最方便的方法是在类声明中进行定义。
二、构造函数和析构函数
1.声明和定义构造函数
构造函数是对类对象进行自动初始化的函数,声明对象时自动调用构造函数。成员名的命名通常使用m_前缀:
class Stock
{
private:
string m_company;
string m_shares;
……
}
2.使用构造函数
C++提供了两种使用构造函数来初始化对象的方式,第一种是显示地调用构造函数:
Stock food = Stock(“World Cabbage”, 250, 1.25);
另一种是隐式地调用:
Stock food(“World Cabbage”, 250, 1.25);
这两种方式等价。
使用new动态分配内存时:
Stock *pstock = new Stock(“World Cabbage”, 250, 1.25);
无法使用对象来调用构造函数,构造函数用来创建对象,而不能通过对象来调用。
3.默认构造函数
当且仅当没有定义任何构造函数时,编译器会提供默认构造函数,它是用于下面这种声明的构造函数:
Stock fluffy_the_cat;
它是默认构造函数的隐示版本,不做任何工作,因此创建了fluffy_the_cat对象,但不初始化其成员,就像int x创建了变量x但是没有提供值一样。
为类提供了构造函数后就必须为它提供默认构造函数,否则下面的声明将出错:
Stock stock1;
如果想要创建对象而不显示地初始化,就必须要提供默认构造函数。定义默认构造函数的方式有两种,一种是没有任何参数:
Stock();
一种是所有参数都有默认值:
Stock(const string &co = “Error”, int n = 0, double pr = 0.0);
只能有一个默认构造函数,所以不要同时使用这两种方式。
4.析构函数
析构函数是这样的:
~Stock() {}
析构函数完成对象过期时的清理工作。析构函数何时被调用是由编译器决定的,通常不显示调用析构函数(特殊情况例外)。如果对象是静态存储的,则析构函数在程序结束时自动被调用;如果对象是自动存储的,则析构函数在执行完代码块时自动被调用;如果对象是通过new创建的,则析构函数在使用delete释放内存时自动被调用。如果没有析构函数,编译器将隐示地提供一个默认析构函数。
构造函数不仅仅可以初始化对象,还可以给对象赋值:
stock1 = Stock(“Nifty foods”, 10, 50.0);
这是通过让构造函数创建一个新的、临时的对象,然后将其内容赋给stock1实现的。随后程序调用析构函数删除该临时对象。
列表初始化:
Stock hot_tip = {“plusplus”, 100, 45.0};
Stock hot_tip {“plusplus”, 100, 45.0};
Stock jol {};
5.const成员函数
const成员函数是保证不会修改调用对象的函数,语法是将const放在函数括号后面:
void Stock::show() const;
三、this指针
this指针指向调用成员函数的对象。
四、对象数组
初始化对象数组的方案是,首先使用默认构造函数创建数组元素,然后用花括号的构造函数创建临时对象,然后将临时对象的内容赋值到数组元素中(像下面的代码一样),因此,要创建对象数组,类必须有默认构造函数。
Stock stocks[4]; //调用默认构造函数
Stock stocks[4] =
{
Stock(“NanoSmart”, 12.5, 20),
Stock(“Boffo Object”, 200, 2.0),
Stock(“Monolithic Obelisks”, 130, 3.25),
Sock(“Fleep Enterprises”, 60, 6.5)
};
五、类作用域
1.作用域为类的常量
在类中声明符号常量使所有的类对象都可用是不错的主意,但是像下面这样是不可行的:
class Bakery
{
private:
const int Months = 12;
double costs[Months];
……
}
因为类声明只是描述了类的形式,并没有创建对象,所以没有用于存储值的空间。下面的两种方法可以实现这个目标:
(1)在类中声明一个枚举:
class Bakery
{
private:
enum {Months = 12};
double costs[Months];
……
}
(2)使用关键字static:
class Bakery
{
private:
static const int Months = 12;
double costs[Months];
……
}
2.作用域内枚举
传统的枚举存在一些问题,枚举定义中的变量可能会发生冲突,就像下面这样:
enum egg {Small, Medium, Large, Jumbo};
enum t_shirt {Small, Medium, Large, XLarge};
这将无法通过编译,因为egg Samll和t_shirt Small位于相同的作用域内,它们将发生冲突。为避免这种问题,C++11提供了一种新枚举,其枚举量的作用域为类,这种枚举的声明类似于下面这样:
enum class egg {Small, Medium, Large, Jumbo};
enum class t_shirt {Small, Medium, Large, XLarge};
也可以使用关键字struct代替class。无论使用哪种方式,都需要使用枚举名来限定枚举量:
egg choice = egg::Large;
t_shirt Floyd = t_shirt::Large;
常规枚举可以自动转换为整型,但类作用域内枚举不能:
enum egg {Small, Medium, Large, Jumbo}; //非类作用域内枚举
enum class t_shirt {Small, Medium, Large, XLarge}; //作用域内枚举
egg one = Medium;
t_shirt rolf = t_shirt::Large;
int king = one; //自动转换为整型
int king = rolf; //不允许自动转换
if (king < Jumbo)
{……}
if (king < t_shirt::Medium) //不允许
{……}
但可以进行显示类型转换:
int Frodo = int (t_shirt::Small);
枚举用某种底层整型类型表示,默认情况下,C++11作用域内枚举的底层类型为int,这里有一种语法,可以做出不同的选择:
enum class : short t_shirt { Small, Medium, Large, XLarge };
:short将底层类型指定为short。但如果没有明确指定,编译器选择的底层类型将随实现而异。
总结
以上就是本文的内容——C++的对象和类,包括C++的抽象和类、构造函数和析构函数、this指针、对象数组、作用域为类的常量和作用域内的枚举。