P12-c++对象和类-05类作用域详细介绍,详细的例子演示!

1. 类作用域

C++类引入了一种新的作用域:类作用域。
在类中定义的名称(如类数据成员名和类成员函数名)的作用域都为整个类,作用域为整个类的名称只在该类中是已知的,在类外是不可知的。
因此,可以在不同类中使用相同的类成员名而不会引起冲突。例如,Stock类的shares成员不同于JobRide类的shares成员。另外,类作用域意味着不能从外部直接访问类的成员,公有成员函数也是如此。也就是说,要调用公有成员函数,必须通过对象:

Stock sleeper("Exclusive Ore",100,0.25); // create object
// use object to invoke a member function
sleeper.show();
show();// invalid -- can't call method directly

同样,在定义成员函数时,必须使用作用域解析运算符:

void Stock::update(double price)
{
    
    
	···
}

总之,在类声明或成员函数定义中,可以使用未修饰的成员名称(未限定的名称)
构造函数名称在被调用时,才能被识别,因为它的名称与类名相同。
在其他情况下,使用类成员名时,必须根据上下文使用直接成员运算符(.)、间接成员运算符(->)或作用域解析运算符(::)。

2. 作用域为类的常量

有时候,使符号常量的作用域为类很有用。
例如,类声明可能使用字面值30来指定数组的长度,由于该常量对于所有对象来说都是相同的,因此创建一个由所有对象共享的常量是个不错的主意。
您可能以为这样做可行:

class Bakery {
    
    
private: 
	const int Months = 12;//declare a constant? FAILS 
	 double costs [Months]; 
};

但这是行不通的,因为声明类只是描述了对象的形式,并没有创建对象。
因此,在创建对象前,将没有用于存储值的空间(实际上,c++11提供了成员初始化,但不适用于前述数组声明,第12章将介绍该 主题)。 然而,有两种方式可以实现这个目标,并且效果相同。
第一种方式是在类中声明一个枚举。
在类声明中声明的枚举的作用域为整个类,因此可以用枚举为整 型常量提供作用域为整个类的符号名称。也就是说,可以这样开始Bakery声明:

class Bakery {
    
    
private: 
	enum {
    
    Months = 12); 
	double costs [Months]; 
} ;

注意,用这种方式声明枚举并不会创建类数据成员。也就是说,所有对象中都不包含枚举。另外,Months 只是一个符号名称,在作用域为整个类的代码中遇到它时,编译器将用30来替换它。
由于这里使用枚举只是为了创建符号常量,并不打算创建枚举类型的变量,因此不需要提供枚举名。
顺便说一句,在很多实现中,ios_base类在其公有部分中完成了类似的工作,诸如ios_base:: fixed等标识符 就来自这里。其中,fixed是ios base类中定义的典型的枚举量。

C++提供了另一种在类中定义常量的方式使用关键字 static

class Bakery
{
    
    
private:
	static const int Months 12
	double costs [Months]:
};

这将创建一个名为 Months的常量,该常量将与其他静态变量存储在一起,而不是存储在对象中。因此,只有一个 Months常量,被所有 Bakery对象共享。第12章将深入介绍静态类成员。在C++98中,只能使用这种技术声明值为整数或枚举的静态常量,而不能存储 double常量。C++11消除了这种限制。

3.作用域内枚举(C++11)

传统的枚举存在一些问题,其中之一是两个枚举定义中的枚举量可能发生冲突。假设有一个处理鸡蛋 和T恤的项目,其中可能包含类似下面这样的代码

enum egg ( Small, Medium, Large, Jumbo);
enum t_shirt Small, Medium, Large, Xlarge);

这将无法通过编译, 因为 egg Small和 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;// the Large enumerator of the egg enum
t_shirt Floyd =t_shirt::Large; // the Large enumerator of the t shirt enum

枚举量的作用域为类后,不同枚举定义中的枚举量就不会发生名称冲突了,而您可继续编写处理鸡蛋和T恤的项目。
C++11还提高了作用域内枚举的类型安全。
在有些情况下,常规枚举将自动转换为整型,如将其赋给int变量或用于比较表达式时,但作用域内枚举不能隐式地转换为整型:

enum egg_old {
    
    Small, Medium, Large, Jumbo}; // unscoped
enum class t_shirt {
    
    Small, Medium, Large, Xlarge}; //scoped
egg_old one = Medium;// unscoped
t_shirt rolf = t_shirt::Large// scoped
int king = one; //implicit type conversion for unscoped
int ring = rolf //not allowed, no implicit type conversio
if (king < Jumbo)	// allowed
	std::cout << "Jumbo converted to int before comparison.\n"

if (king < t_shirt::Medium) //not allowed
	std::cout << "Not allowed: < not defined for scoped enum\n"

但在必要时,可进行显式类型转换:
int Frodo= int(t_shirt: Small); // Frodo set to 0
枚举用某种底层整型类型表示,在C++98中,如何选择取决于实现,因此包含枚举的结构的长度可能随系统而异。
对于作用域内枚举,C++11消除了这种依赖性。默认情况下,C++11作用域内枚举的底层类型为int。
另外,还提供了一种语法,可用于做出不同的选择:

// underlying type for pizza is short
enum class: short pizza {
    
    Small, Medium, Large, XLarge};

shot将底层类型指定为 short。底层类型必须为整型。
在C++11中,也可使用这种语法来指定常规枚举的底层类型,但如果没有指定,编译器选择的底层类型将随实现而异。

3. 实例演示类作用域和作用域为类的常量

class_scope.cpp

#include <iostream>
#include <string>
 /*
    author:梦悦foundation
    公众号:梦悦foundation
    可以在公众号获得源码和详细的图文笔记
*/

using namespace std;

class Demo {
    
    
private:
	const int Months = 12;//declare a constant? FAILS 
	double costs [Months];

};

int main(int argc, char *argv[]) 
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;

	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
    return 0;
}

编译运行结果:

meng-yue@ubuntu:~/MengYue/c++/object_class/05$ g++ -o class_scope class_scope.cpp
class_scope.cpp:14:16: error: invalid use of non-static data member ‘Demo::Months’
  double costs [Months];
                ^~~~~~
class_scope.cpp:13:21: note: declared here
  const int Months = 12;//declare a constant? FAILS
                     ^~
meng-yue@ubuntu:~/MengYue/c++/object_class/05$

在创建对象前,将没有用于存储值的空间

1. 第一种方式是在类中声明一个枚举。

class_scope01.cpp

class Demo {
    
    
private:
	enum {
    
    Months = 12};
	double costs [Months];

public:
	void Show();
};

void Demo::Show()
{
    
    
	cout << "double size:" << sizeof(double) << ", sizeof(costs):" << sizeof(costs) << endl;
}

编译运行的结果:说明这种方式是可行的!

meng-yue@ubuntu:~/MengYue/c++/object_class/05$ ./class_scope01
---------------开始--->公众号:梦悦foundation---------------
double size:8, sizeof(costs):96
---------------结束--->公众号:梦悦foundation---------------
meng-yue@ubuntu:~/MengYue/c++/object_class/05$

2. 在类中定义常量的方式使用关键字 static

class_scope02.cpp

class Bakery
{
    
    
private:
	static const int Months = 12;
	double costs [Months]:
};

这个的运行结果和上面的是一样的!

猜你喜欢

转载自blog.csdn.net/sgy1993/article/details/113621200