P12-c++ object and class-05 class scope detailed introduction, detailed example demonstration!

1. Class scope

C++ classes introduce a new scope: class scope. The scope
of the names defined in the class (such as the name of the class data member and the name of the class member function ) is the entire class, and the scope is the name of the entire class that is only known in the class, but not outside the class.
Therefore, the same class member name can be used in different classes without causing conflicts. For example, the shares member of the Stock class is different from the shares member of the JobRide class. In addition, class scope means that the members of the class cannot be accessed directly from the outside, and the same is true for public member functions. In other words, to call a public member function, you must pass the object:

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

Similarly, when defining member functions, you must use scope resolution operators:

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

In short, in class declarations or member function definitions, you can use unmodified member names (unqualified names). The
constructor name can only be recognized when it is called, because its name is the same as the class name.
In other cases, when using class member names, you must use the direct member operator (.), indirect member operator ( ->), or scope resolution operator ( ::) according to the context .

2. The scope is the constant of the class

Sometimes it is useful to make the scope of a symbolic constant a class.
For example, the class declaration may use the literal value 30 to specify the length of the array. Since the constant is the same for all objects, it is a good idea to create a constant that is shared by all objects.
You might think this is feasible:

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

But this does not work, because the declaration of the class only describes the form of the object, and does not create the object.
Therefore, before the object is created, there will be no space for storing the value (in fact, c++11 provides member initialization, but it does not apply to the aforementioned array declaration, which will be introduced in Chapter 12). However, there are two ways to achieve this goal with the same effect.
The first way is to declare an enum in the class.
The scope of the enumeration declared in the class declaration is the entire class, so the enumeration can be used to provide the symbolic name of the entire class with the scope for integer constants . In other words, you can start the Bakery statement like this:

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

Note that declaring enumerations in this way does not create class data members. In other words, no enumeration is included in all objects. In addition, Months is just a symbolic name, and the compiler will replace it with 30 when it encounters it in code whose scope is the entire class.
Since enumeration is used here only to create symbolic constants, and it is not intended to create variables of enumeration type, there is no need to provide enumeration names.
By the way, in many implementations, the ios_base class completes similar work in its public part, and identifiers such as ios_base:: fixed come from here. Among them, fixed is a typical enumeration defined in the ios base class.

C++ provides another way to define constants in classes using the keyword static

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

This will create a constant called Months, which will be stored with other static variables instead of in the object. Therefore, there is only one Months constant, which is shared by all Bakery objects. Chapter 12 will introduce static class members in depth. In C++98, this technique can only be used to declare static constants whose values ​​are integers or enumerations, but cannot store double constants. C++11 eliminates this limitation.

3. Enumeration in scope (C++11)

There are some problems with traditional enumeration, one of which is that the enumerations in two enumeration definitions may conflict. Suppose there is a project dealing with eggs and T-shirts, which may contain code similar to the following

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

This will fail to compile, because egg Small and t_shirt Small are in the same scope and they will conflict. To avoid this problem, C++11 provides a new enumeration whose scope is a class.
The declaration of this enumeration is similar to the following

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

You can also use the keyword struct instead of class.
No matter which method you use, you need to use the enumeration name to qualify the enumeration

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

After the scope of the enumeration is a class, there will be no name conflicts between the enumerations in different enumeration definitions, and you can continue to write items that deal with eggs and T-shirts.
C++11 also improves the type safety of enumeration in scope.
In some cases, regular enumerations will be automatically converted to integer types, such as when they are assigned to int variables or used in comparison expressions, but in-scope enumerations cannot be implicitly converted to integer types:

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"

However, when necessary, explicit type conversion can be performed: the
int Frodo= int(t_shirt: Small); // Frodo set to 0
enumeration is represented by a certain underlying integral type. In C++98, how to choose depends on the implementation, so the length of the structure containing the enumeration may vary from system to system.
For in-scope enumeration, C++11 eliminates this dependency. By default, the underlying type of enumeration in the scope of C++11 is int.
In addition, a grammar is provided that can be used to make different choices:

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

Shot specifies the underlying type as short. The underlying type must be an integer.
In C++11, this syntax can also be used to specify the underlying type of a regular enumeration, but if it is not specified, the underlying type selected by the compiler will vary depending on the implementation.

3. The example demonstrates that the scope of the class and the scope of the class are constants

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;
}

Compile and run results:

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$

Before the object is created, there will be no space for storing the value

1. The first way is to declare an enumeration in the class.

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;
}

The result of compiling and running: It shows that this method is feasible!

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. Use the keyword static to define constants in a class

class_scope02.cpp

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

The result of this operation is the same as the above!

Guess you like

Origin blog.csdn.net/sgy1993/article/details/113621200