第七章:类的其他特性+返回*this的成员函数+类类型+友元再探

一、编写自己的Screen类。
知识点1:类可以自定义某种类型在类中的别名———通过typedef和using;
知识点2:如果我们需要合成的默认构造函数,在空列表的构造函数后加上=default即可;
知识点3:类的成员也可以重载,参数列表数量或者类型上不同;
知识点4:在变量前加关键字mutable,变为可变数据成员,即使是在一个const的对象函数中也可以被修改;
知识点5:类内初始值,直接用=赋予的方式是C++11新特性,也就是VS2013以上的版本才支持;
知识点6:当某个数据成员在构造函数初始化列表中忽略,它将以默认构造函数的方式隐式初始化;

			#ifndef Cccc//第一次包含本头文件时,#ifndef判断为真,预处理器将处理后面的内容直到#endif,此时的预处理变量Cccc已定义
            #define Cccc//第二次包含本头文件时,#ifndef判断为假,预处理器将忽略后面的内容
            #include <string>
			class Screen {
			public:
				using pos = std::string::size_type;//std库中的string类的sizetype类型
				Screen() = default;
				Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c)
				{
				}
				char get() const { return contents[cursor]; }
				char get(pos r, pos c) const { return contents[r * width + c]; }
			private:
				pos cursor = 0;
				pos height = 0, width = 0;
				std::string contents;
			};
			#endif//只要简单的加上就好了,无视C++中的作用域规则,作用是防止头文件被重复包含
			/*
			c++ string::size_type详解
				string::size_type类型
				从逻辑上来讲,size()成员函数似乎应该返回整型数值,或如2.2节“建议”中所述的无符号整数。但事实上,size操作返回的是string::size_type类型的值。
				我们需要对这种类型做一些解释。string类类型和许多其他库类型都定义了一些伙伴类型(companion types)。这些伙伴类型使得库类型的使用是机器无关的(machine-independent)。
				size_type就是这些伙伴类型中的一种。它定义为与unsigned型(unsigned int或unsigned long)具有相同的含义,而且可以保证足够大可存储任意string对象的长度。
				为了使用由string类型定义的size_type类型,程序员必须加上作用域操作符来说明所使用的size_type类型是由string类定义的。
				任何存储string的size操作结果的变量必须为string::size_type类型。特别重要的是,不要把size的返回值赋给一个int变量。
				虽然我们不知道string::size_type的确切类型,但可以知道它是unsigned型(2.1.1节)。对于任意一种给定的数据类型,它的unsigned型所能表示的最大正数值比对应的signed要大一倍。
				这个事实表明size_type存储的string长度是int所能存储的两倍。
				使用int变量的另一个问题是,有些机器上int变量的表示范围太小,甚至无法存储实际并不长的string对象。如在有16位int型的机器上,int类型变量最大只能表示32767个字符的string对象。
				而能容纳一个文件内容的string对象轻易就会超过这个数字。因此,为了避免溢出,保存一个string对象size的最安全的方法就是使用标准库类型string:: size_type。
				string类类型和许多其他库类型都定义了一些配套类型(companion type)。通过这些配套类型,库类型的使用就能和机器无关(machine-independent)。string::size_type定义为unsigned型,可以保证足够大的存储string对象的长度。
				注意,任何存储string的size操作结果的变量必须为string::size_type类型。尤其不能把size的返回值赋给一个int变量。(因为size返回的是一个unsigned类型,而int是signed类型。size能表达的大小是int的2倍)。
			string str("some string");   //通过字符串字面值赋值给串
			for (string::size_type ix = 0; ix != str.size(); ++ix)   //此处不该为int     用!=,而不用<=
			{
				cout<<str[ix]<<endl;
			}
			vector<int> ivec;
			for(vector<int>::iterator ix = ivec.begin(); ix != ivec.end(); ++ix)
				//此处不该为int     用!=,而不用<=
			{
				*ix = 0; //将各个元素赋值为0
			}
			综上所述:string::size_type 等价于 unsigned ,使用情况为存储字符串的大小
			*/

二、给Screen类添加三个构造函数:一个默认构造函数;另一个构造函数接受宽和高的值,然后将contents初始化给定数量的空白;第三个构造函数接受宽和高的值以及一个字符,该字符作为初始化之后屏幕的内容。

		Screen() = default; // 第一个构造函数
		Screen(pos ht, pos wd) : height(ht), width(wd), contents(ht * wd, ' ') {} // 第二个构造函数
		Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c)
		{
		} // 第三个构造函数

三、Screen能安全的依赖于拷贝和赋值操作的默认版本吗?如果能为什么?如果不能,为什么?

解析:只有内置类型和string类型可以依赖于操作的默认版本。

四、通过this指针使用成员的做法虽然合法,但是有点多余。讨论显示地使用指针访问成员的优缺点。

解析:优点:1:当需要将一个对象作为整体引用而不是引用对象的一个成员时,使用this,则该函数返回对调用该函数的对象的引用。 
2:可以非常明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参。  
      缺点:不必要使用,代码多余。

五、定义一对类X和Y,其中X包含一个指向Y的指针,而Y包含一个类型为X的对象。
知识点1:可以将类当作一种类型来看待,两个类即使成员部分完全相同,也属于不同的类型;
知识点2:类允许包含指向它自身类型的指针或者引用;
知识点3:创建一个类的对象之前必须先定义该类,仅仅声明是无法让编译器了解到该类需要多少空间的;

			#ifndef Cccc//第一次包含本头文件时,#ifndef判断为真,预处理器将处理后面的内容直到#endif,此时的预处理变量Cccc已定义
			#define Cccc//第二次包含本头文件时,#ifndef判断为假,预处理器将忽略后面的内容
			class X;//事先声明
			class Y
			{
				X object;
			};
			 
			class X
			{
				Y *my_pointer = NULL;
			};
			#endif//只要简单的加上就好了,无视C++中的作用域规则,作用是防止头文件被重复包含

六、定义你自己的Screen和Window_mgr,其中clear是Window_mgr的成员,是Screen的友元。

		解析:	知识点1:若想将一组重载函数声明为一个类的友元,那么必须逐个进行声明
				知识点2:在类内声明的友元必须在类内或者类外进行定义之后才可以使用
				此题在clear()函数之前加 friend 关键字即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N1314N

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值