C++ primer 第三章 标准库类型

本章主要讲了标准库类型,其中主要从以下几个方面进行了说明。
第一:命名空间的using声明:
第二:标准库string类型:定义和初始化(三种)、读写、getline/string重点
第三:标准库vector类型:定义和初始化、对象操作
第四:迭代器简介(不懂)
第五:标准库bitset类型(不懂)
小结:
①变量和基本类型等都是低级数据类型,标准库类型更为高级更为抽象。其中最为重要的为string和vector标准库类型。
②使用using声明可以在不需要加前缀namespace_name::情况下,一个using只能作用于一个命名空间成员。
③using std::cin;   using std::cout;  using std::endl;  后面程序中可以不写std::.
④getline函数用于读取整行,eg:while (getline(cin,line))   ^^^^^^^return 0;
⑤vector值初始化、对象操作(size)、添加元素、下标操作

 

  1. class Sale_item
  2. {
  3. public:
  4. // 隐式使用string 的默认构造函数初始化 isbn
  5. Sale_item():price(0.0){}
  6. Sale_item(const string &book):isbn(book), price(0.0){}
  7. // 建议使用默认实参,将上述2个构造函数合并。如下:
  8. // Sale_item(const string &book = ""):isbn(book), price(0.0){}
  9. private:
  10. string isbn;
  11. double price;
  12. };
class Sale_item
{
public:
	// 隐式使用string 的默认构造函数初始化 isbn
	Sale_item():price(0.0){}	

	Sale_item(const string &book):isbn(book), price(0.0){}

	// 建议使用默认实参,将上述2个构造函数合并。如下:
	// Sale_item(const string &book = ""):isbn(book), price(0.0){}
private:
	string isbn;
	double price;
};

合成的默认构造函数
如果,类没有定义构造函数,编译器将会自动生成一个默认的构造函数。
但是,如果已经定义过构造函数(哪怕只有1 个), 编译器就不会再生成默认构造函数。
理由:因为一个类,在某种情况下,需要控制对象的初始化,则,该类很可能在所有情况下都需要控制。

合成的默认构造函数,的初始化规则,与变量的初始化规则相同。
类类型,使用各自的默认构造函数,来初始化
内置、复合类型,如:指针、数组,只对定义在全局作用域中的对象才初始化,
定义局部作用域中,则,内置、复合类型不初始化,处于未定义状态。


类通常,都应该定义一个默认构造函数

假设:NoDefault ,是一个类,它具有接受一个 string 实参的构造函数,
这种情况下,编译器,不会生成默认构造函数。
于是,
1、当我定义一个类 A,具有 NoDefault 类型的成员,则,
A 的所有构造器,都必须通过传递一个初始 string 来初始化 NoDefault 类型的成员

2、当我定义一个类 A,具有 NoDefault 类型的成员,则,
编译器将不会生成 A 的默认构造器。只能自己显示定义

3、NoDefault 类型,不能用作动态分配数组的元素类型。

  1. int *iArr = new int[10];
  2. // 上式可行,下式报错
  3. NoDefault *arr = new NoDefault[10];
int *iArr = new int[10];

// 上式可行,下式报错
NoDefault *arr = new NoDefault[10];

4、NoDefault 类型的静态分配数组,也必须为每个元素提供显示的初始化
5、如果有保存 NoDefault 对象的容器,如:vector,
则,容器的构造函数,不仅要提供容器大小,也要提供元素初始化式。



  1. // 这是一个函数声明,函数返回类型:Sales_item
  2. Sales_item myObj();
  3. //
  4. Sales_item myObj2;
  5. // 创建一个 Sales_item 对象,并用默认构造函数初始化
  6. Sales_item myObj3 = new Sales_item();
// 这是一个函数声明,函数返回类型:Sales_item
Sales_item myObj();

// 
Sales_item myObj2;

// 创建一个 Sales_item 对象,并用默认构造函数初始化
Sales_item myObj3 = new Sales_item();


隐式类型转换

  1. class Sales_item
  2. {
  3. public:
  4. Sales_item(const string &book = ""):isbn(book), units_sold(0), revenue(0.0){}
  5. // explicit 只能用于,类内部的构造函数声明上,在类的定义体外部则不用重复它
  6. explicit Sales_item(istream &is);
  7. Sales_item();
  8. bool same_isbn(Sales_item item)
  9. {
  10. return item.isbn == isbn;
  11. }
  12. private:
  13. string isbn;
  14. int units_sold;
  15. double revenue;
  16. };
  17. // 错误: explicit 只能在类内部的构造函数声明上
  18. explicit Sales_item::Sales_item(istream &is)
  19. {
  20. /* ... */
  21. }
  22. /* ... */
  23. string null_book = "9-999-9999-9";
  24. Sales_item item_a = Sales_item("1-111-1111-1");
  25. // 以下会隐式调用构造函数,生成一个 Sales_item 对象,来进行比较
  26. // 但这种隐式转换,未必是我们真正想要的。
  27. // 为阻止这种隐式转换,可以在构造函数前,使用 explicit 关键字
  28. item_a.same_isbn(null_book);
  29. // 建议使用下面的方式,避免错误
  30. item_a.same_isbn(Sales_item(null_book));
class Sales_item
{
public:

	Sales_item(const string &book = ""):isbn(book), units_sold(0), revenue(0.0){}	
	// explicit 只能用于,类内部的构造函数声明上,在类的定义体外部则不用重复它
	explicit Sales_item(istream &is);
	Sales_item();

	bool same_isbn(Sales_item item)
	{
		return item.isbn == isbn;
	}
private:
	string isbn;
	int units_sold;
	double revenue;
};
// 错误: explicit 只能在类内部的构造函数声明上
explicit Sales_item::Sales_item(istream &is)
{
	/* ... */
}

/* ... */
string null_book = "9-999-9999-9";
Sales_item item_a = Sales_item("1-111-1111-1");

// 以下会隐式调用构造函数,生成一个 Sales_item 对象,来进行比较
// 但这种隐式转换,未必是我们真正想要的。
// 为阻止这种隐式转换,可以在构造函数前,使用 explicit 关键字
item_a.same_isbn(null_book);

// 建议使用下面的方式,避免错误
item_a.same_isbn(Sales_item(null_book));


  1. // 没有定义构造函数、并且,全体数据成员都是 public 的类,
  2. // 可以采用,与数组元素相同的方式,来初始化成员
  3. // 但,还是推荐,使用构造函数
  4. struct Data
  5. {
  6. int ival;
  7. char *ptr;
  8. };
  9. Data val1 = {0, 0};
// 没有定义构造函数、并且,全体数据成员都是 public 的类,
// 可以采用,与数组元素相同的方式,来初始化成员
// 但,还是推荐,使用构造函数
struct Data
{
	int ival;
	char *ptr;
};
Data val1 = {0, 0};


友元,允许一个类,将自己的,非公有成员的访问,授权给,指定的类或者函数。
它只能出现在类定义的内部。通常,将所有的友元声明,成组地放到类定义的开始或者结尾。

  1. class Screen
  2. {
  3. public:
  4. typedef string::size_type index;
  5. private:
  6. int height;
  7. int width;
  8. // 友元不是 Screen的成员,
  9. // 它可以出现在 Screen 类定义体中的,任何地方。
  10. // 并且,不受访问控制(private、public)的影响
  11. friend class Window_Mgr;
  12. // 将,其他类的成员函数,设置为友元
  13. friend Window_Mgr& Window_Mgr::relocate(Screen::index, Screen::index, Screen&);
  14. };
  15. class Window_Mgr
  16. {
  17. public:
  18. Window_Mgr& relocate(Screen::index r, Screen::index c, Screen &s)
  19. {
  20. s.height += r;
  21. s.width += c;
  22. return *this;
  23. }
  24. private:
  25. };
class Screen
{
public:
	typedef string::size_type index;
private:
	int height;
	int width;

	// 友元不是 Screen的成员,
	// 它可以出现在 Screen 类定义体中的,任何地方。
	// 并且,不受访问控制(private、public)的影响
	friend class Window_Mgr;

	// 将,其他类的成员函数,设置为友元
	friend Window_Mgr& Window_Mgr::relocate(Screen::index, Screen::index, Screen&);	
};
class Window_Mgr
{
public:
	Window_Mgr& relocate(Screen::index r, Screen::index c, Screen &s)
	{
		s.height += r;
		s.width += c;
		return *this;
	}
private:

};


要将类的成员函数,设为友元,则这个类必须先定义
要将类 或者 非成员函数 设为友元,则,不需要预先声明。
(P398,例子,貌似有误)

全局对象,会破坏封装性,而,类中定义的 静态成员,则能保持很好的封装性。
static 数据成员,与类相关联,而不是与类的对象关联。
static 成员函数,没有 this 形参。

  1. class Account
  2. {
  3. public:
  4. void applyint(){ amount += amount * interestRate; }
  5. static double rate() { return interestRate; }
  6. static void rate(double);
  7. private:
  8. string owner;
  9. double amount;
  10. static double interestRate;
  11. static double initRate();
  12. // 例外,const 类型的静态数据成员,可以在类定义体中初始化
  13. // 但是,即使如此,也必须在外部,进行定义
  14. static const int period = 30;
  15. };
  16. // 外部定义,但此时,无须提供初始化式
  17. const int Account::period;
  18. // 内部已经声明为 static 了
  19. // 外部定义的时候,不需要再指定 static
  20. // static 不能声明为 const、也不能声明为 虚函数
  21. // 声明为 const 是承诺不修改该函数所属的对象,
  22. // 然而, static 函数,不属于任何对象,它只与类关联
  23. void Account::rate(double newRate)
  24. {
  25. interestRate = newRate;
  26. }
  27. // static 数据成员,必须在类定义体的外部定义(刚好一次)
  28. // 一旦成员名出现,static 成员的定义,就在类作用域中了
  29. // 因此,可以直接使用 私有成员函数 initRate
  30. double Account::interestRate = initRate();
  31. Account ac1;
  32. Account *ac2 = &ac1;
  33. double rate;
  34. rate = ac1.rate();
  35. rate = ac2->rate();
  36. rate = Account::rate();
class Account
{
public:
	void applyint(){ amount += amount * interestRate; }
	static double rate() { return interestRate; }
	static void rate(double);
	
private:
	string owner;
	double amount;
	static double interestRate;
	static double initRate();

	// 例外,const 类型的静态数据成员,可以在类定义体中初始化
	// 但是,即使如此,也必须在外部,进行定义
	static const int period = 30;
};
// 外部定义,但此时,无须提供初始化式
const int Account::period;

// 内部已经声明为 static 了
// 外部定义的时候,不需要再指定 static
// static 不能声明为 const、也不能声明为 虚函数
// 声明为 const 是承诺不修改该函数所属的对象,
// 然而, static 函数,不属于任何对象,它只与类关联
void Account::rate(double newRate)
{
	interestRate = newRate;
}

// static 数据成员,必须在类定义体的外部定义(刚好一次)
// 一旦成员名出现,static 成员的定义,就在类作用域中了
// 因此,可以直接使用 私有成员函数 initRate
double Account::interestRate = initRate();
Account ac1;
Account *ac2 = &ac1;
double rate;
rate = ac1.rate();
rate = ac2->rate();
rate = Account::rate();

  1. class Bar
  2. {
  3. public:
  4. private:
  5. // static 数据成员的类型,可以是该成员所属的类类型。
  6. static Bar mem1;
  7. Bar *mem2;
  8. // 错误
  9. Bar mem3;
  10. };
  11. class Screen
  12. {
  13. public:
  14. Screen& clear(char = bkground);
  15. private:
  16. // static 数据成员,可以作为默认实参。
  17. static const char bkground = '#';
  18. };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值