⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2local.html

📁 Visual C++ has been one of most effective tool for the large industrial applications. This book is t
💻 HTML
字号:
<html>
<head>
    <title>Local Scope</title>
    <meta  name="description" content="Local scopes in C++">
    <meta name="keywords" content="scope, local, constructor, destructor, stack">
    <link rel="stylesheet" href="rs.css" tppabs="http://www.relisoft.com/book/rs.css">
</head>

<body background="margin.gif" tppabs="http://www.relisoft.com/book/images/margin.gif" bgcolor="#FFFFDC">

<!-- Main Table -->
<table cellpadding="6">
    <tr>
    <td width="78">
	&nbsp;
    <td>

<h3>Local scope</h3>
<p class=topics>
Scope of main, passing arguments to constructors, integer type. Private data members, initialization, embedded local scopes, the for loop.

<p>
Global scope extends outside of any braces. It is activated (that is, ready to use, all objects constructed) before main is executed, and deactivated (all objects destroyed) after main is exited. Local scopes, on the other hand, are delimited by braces (well, not always, we'll see in a moment that there are cases where braces can be omitted). Local scope is activated when the flow of the program enters it, and deactivated when it leaves it. Objects in local scope are constructed whenever their definition is encountered, and destroyed when the scope is exited. Such objects are also called <i>automatic</i> (because they are automatically created and destroyed), or stack objects (because they occupy memory that is allocated on the program's stack).
<p>
Our first example of the use of local scope creates a local <var>World</var> called <var>myWorld</var> within the scope of <var>main()</var>. The <var>myWorld</var> object is constructed right after entering <var>main()</var>, then "Hello from main" is printed, and finally the object is destroyed right before exiting the scope of <var>main</var>. The global <var>World</var> is still constructed before <var>main()</var> and destroyed after <var>main()</var>.
<p>
Another modification to our original program is the use of an integer as an argument to the constructor of <var>World</var>. An integer is of the predefined type <var>int</var>. Its size is compiler dependent. In the constructor, this argument (called <var>i</var>) is sent to the standard output. Notice how clever the <var>std::cout</var> object is. It accepts strings of characters and prints them as strings and it accepts integers and prints them as decimal numbers. And, as you can see,  you can chain arguments to std::cout one after another.
<p>
Since the constructor expects an argument, we have to provide it when we create the object. Here we just specify it in parentheses after the name of the object being created
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>World TheWorld (1);</pre>
</table>
<!-- End Code -->

<p>
When the constructor of <var>TheWorld</var> is executed it prints "Hello from 1."

<tr>
<td class=margin valign=top width="78">
Download the whole <b>World</b> series of sources. <br><a href="javascript:if(confirm('http://www.relisoft.com/book/lang/scopes/source/worlds.zip  \n\nThis file was not retrieved by Teleport Pro, because it is linked too far away from its Starting Address. If you increase the in-domain depth setting for the Starting Address, this file will be queued for retrieval.  \n\nDo you want to open it from the server?'))window.location='http://www.relisoft.com/book/lang/scopes/source/worlds.zip'" tppabs="http://www.relisoft.com/book/lang/scopes/source/worlds.zip"><img src="brace.gif" tppabs="http://www.relisoft.com/book/images/brace.gif" width=16 height=16 border=1 alt="Download!"><br>source</a>
<td>


<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>#include &lt;iostream&gt;

class <span class=method>World</span> 
{
public:
    World (int i)
    {
        std::cout &lt;&lt; "Hello from " &lt;&lt; i &lt;&lt; ".\n";
    }

    ~World ()
    {
        std::cout &lt;&lt; "Good bye.\n";
    }
};

World TheWorld (1);

int main()
{
    
    World myWorld (2);
    std::cout &lt;&lt; "Hello from main!\n";
}</pre>
</table>
<!-- End Code -->

<p>
There's still something missing. How do we know which object printed the first "Good bye." and which object printed the second one? Our objects don't remember their identity. In fact they don't remember anything! But before we fix that, let me digress philosophically. 
<p>
Here we are talking about object oriented programming and I haven't even defined what I mean by an object. <p>
So here we go: 
<!-- Definition -->
<p>
<table border=4 cellpadding=10><tr>
    <td bgcolor="#ffffff" class=defTable>

Definition: An object is something that has identity.</table>
<!-- End Definition -->
<p>
If you can think of something that doesn't have an identity, it's not an object. Beauty is not an object. But if you could say "this beauty is different from the one over there," you would give the two beauties their identities and they would become objects. We sometimes define classes that have non-object names. That just means that we give an old name a new "objectified" meaning. In general, though, it's not such a great idea. If possible one should stick to <i>countable nouns</i>.
<p>
I didn't mean to say that our <var>World</var>s didn't have identity, because they did. They were just not aware of it. Let's give them memory, so that they'll be able to remember who they are.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>#include &lt;iostream&gt;

class <span class=method>World</span>
{
public:
    World (int id)
       : _identifier (id)
    {
        std::cout &lt;&lt; "Hello from " &lt;&lt; _identifier &lt;&lt; ".\n";
    }

    ~World ()
    {
        std::cout &lt;&lt; "Good bye from " &lt;&lt; _identifier &lt;&lt; ".\n";
    }
private:
    const int _identifier;
};

World TheWorld (1);

int main ()
{
    World myWorld (2);
    for (int i = 3; i &lt; 6; ++i)
    {
        World aWorld (i);
    }
    World oneMoreWorld (6);
}
</pre>
</table>
<!-- End Code -->

<p>
Several new things require explanation. Let's do it top-down. In main, we create our local <var>World</var>, <var>myWorld</var>, with an id of 2 (this time the <var>World</var> will remember it until it is destroyed). Next we have a for loop. The meaning of it is the following: For integer <var>i</var> starting from 3 as long as it's less than 6, incremented every time the body of the loop is executed (that's the meaning of <var>++i</var>), do this: Open the scope, define a <var>World</var> called <var>aWorld</var> with an id equal to the current value of <var>i</var>, close the scope. 
<p>
After the loop is done iterating, one more <var>World</var> is defined called <var>oneMoreWorld</var>. It has the id of 6.
The braces delimiting the scope of the for loop may be omitted. This is because here the body of the loop consists of a single statement. So, in fact, we could have written the loop as in Figure 3 and the program would still execute exactly the same way.

<p><img src="nobrace.gif" tppabs="http://www.relisoft.com/book/lang/scopes/images/nobrace.gif" width=222 height=68 border=0 alt="Scope, no braces.">
<p class=caption>Figure 3 A scope without braces.

<p>
The body of the for loop forms a separate scope within the scope of main. When the program enters this scope, the objects from the outer scope(s) are not destroyed. In fact, if there is no name conflict, they are still visible and accessible. There would be name conflict if <var>myWorld</var> were called <var>aWorld</var>. It would be perfectly okay, only that the outer <var>aWorld</var> would be temporarily inaccessible within the for loop: the name of the outer <var>aWorld</var> would be hidden by the name of the inner <var>aWorld</var>. We'll see later what exactly <i>accessible</i> means.

<p>
<!-- Sidebar -->
<table width="100%" border=0 cellpadding=5><tr>
<td width=10>&nbsp;</td>
<td bgcolor="#cccccc" class=sidebar>
What is the scope of the variable <var>i</var> that is defined in the header of the <var>for</var> loop?
<!-- Code -->
<table width="100%" cellspacing=10><tr>
	<td class=codeTable>
<pre>for (int i = 3; i &lt; 6; ++i)
{
   World aWorld (i);
}</pre>
	</td></tr>
</table>
<!-- End Code -->
This is actually a nontrivial question. It used to be that its scope extended beyond the scope of the loop. That's no longer true. The scope of a variable defined in the head of a loop (or the <var>if</var> statement, when we get to it) is that of the loop itself. Notice that it's not the same as the scope of the <i>body</i> of the loop. Variables defined in the body of the loop are re-initialized on every iteration. The ones defined in the head are initialized once, at loop entry. However, once you exit the loop, neither are accessible.

</td></table>
<!-- End Sidebar -->


<p>
We still have our global <var>World</var>, <var>TheWorld</var>, with an id of 1. 
<p>
The class <var>World</var> has a data member <var>_identifier</var>. Its type is <var>int</var> and it's <var>const</var> and <var>private</var>. Why is it private? None of your business. Okay, okay... It's called <i>data hiding</i>. It means: today it is implemented like this, tomorrow, who knows. Maybe an <var>int</var>, maybe a string, and maybe not at all. 
If the <var>_identifier</var> weren't private, it would be like with these hidden functions in MS DOS that everybody knew about: Applications started using them and the developers of MS DOS had to keep them forever for compatibility. Not so in our <var>World</var>. The compiler will make sure that nobody, except the <var>World</var> itself, has access to private members. 
<p>
The keyword <var>const</var> means that nobody can change the value of <var>_identifier</var> during the lifetime of the object. It is physically (or at least "compilatorily") impossible. But even a <var>const</var> has to be initialized some place or another. The compiler provides just one little window when we can (and in fact have to) initialize a <var>const</var> data member. It is in the <i>preamble</i> to the constructor. Not even in the body of the constructor--only in the preamble itself can we initialize a <var>const</var> data member. Preamble is the part of the constructor that starts with a colon and contains a comma-separated list of data members followed by their initializers in parentheses. In our preamble <var>_identifier</var> is initialized with the value of <var>id</var>.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>    World (int id)
       : _identifier (id)
    {
        std::cout &lt;&lt; "Hello from " &lt;&lt; _identifier &lt;&lt; ".\n";
    }</pre>
</table>
<!-- End Code -->
<p>
Once <var>_identifier</var> is initialized, its value for the particular instance of <var>World</var> never changes (later we'll learn how to modify non-constant data members). When the destructor of this object is called, it will print the value that was passed to it in the constructor. So when we see "Good bye from 1." we'll know that it's the end of <var>TheWorld</var> (as opposed to the end of <var>aWorld</var>).
<p>
Why does <var>_identifier</var> have an underscore in front of it? It's a convention. In this book the names of all private data members will start with an underscore. Once you get used to it, it actually helps readability. Of course, you can use your own convention instead. In fact everybody may come up with their own conventions, which is exactly what happens all the time.

<tr>
<td class=margin valign=bottom>
<img src="bug.gif" tppabs="http://www.relisoft.com/book/images/bug.gif" width=25 height=25 border=0 alt="rotten">
<td>

<!-- Sidebar -->
<table width="100%" border=0 cellpadding=5><tr>
<td width=10>
<td bgcolor="#cccccc" class=sidebar>

Speaking of conventions--I will absolutely insist on the brace positioning convention, and for a good reason: In the style of programming that this book promotes, scopes play a central role. It is of paramount importance for the readability of code to make scopes stand out graphically. Therefore:
<!-- Definition -->
<p><table border=4 cellpadding=10><tr>
    <td bgcolor=white class=defTable>

The opening brace of any scope should be vertically aligned with the closing brace of that scope.
</table>
<!-- End Definition -->
The screen and printer paper saving convention of yesteryear 
    <!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>for (int i = 3; i &lt; 6; ++i) <b>{</b> // &lt;- BAD!!!
    World aWorld (i);
}
</pre>
</table>
<!-- End Code -->

is declared harmful to program maintainability.

<td width=10>
</table>
<!-- End Sidebar -->

<tr>
<td class=margin valign=top>

<td>


<p class=summary>
To summarize, objects may have their own memory, or state. The state data members are preferably kept private. They are best initialized in the preamble to the constructor, so that the object is in a consistent state immediately after its birth. The for loop creates its own scope. This scope is entered and exited during every iteration (this is why you see all these "Good bye from 3, 4, 5" messages). In fact a matched pair of braces can be put anywhere within another scope,  just to form a sub-scope.


</table>
<!-- End Main Table -->
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -