📄 3embed.html
字号:
<html>
<head>
<title>Embedded Objects</title>
<meta name="description" content="Object embedding in C++">
<meta name="keywords" content="embedding, class, data, member, constructor, destructor">
<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">
<td>
<h3>Embedded objects</h3>
<p class=topics>
Embeddings, initialization of embeddings, order of construction/destruction.
<p>
We've seen data members of type int--one of the built in types. The beauty of C++ is that it makes virtually no distinction between built in types and the ones defined by the programmer. When a data member of some class is of a user defined type, it is called an embedded object. In the following example <var>Matter</var> is embedded in <var>World</var> (I just gave matter identity. You know, this <i>matter</i> here is much more stable than the one in the neighboring universe.) Another way to put it is--<var>World</var> contains <var>Matter</var>.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>#include <iostream>
class <span class=method>Matter</span>
{
public:
Matter (int id)
: _identifier(id)
{
std::cout << " Matter for " << _identifier << " created\n";
}
~Matter ()
{
std::cout << " Matter in " << _identifier << " annihilated\n";
}
private:
const int _identifier;
};
class <span class=method>World</span>
{
public:
World (int id)
: _identifier (id), _matter (_identifier) // initializing embeddings
{
std::cout << "Hello from world " << _identifier << ".\n";
}
~World ()
{
std::cout << "Good bye from world " << _identifier << ".\n";
}
private:
const int _identifier;
const Matter _matter; // Embedded object of type Matter
};
World TheUniverse (1);
int main ()
{
World myWorld (2);
}
</pre>
</table>
<!-- End Code -->
<p>
What's interesting in this example is the preamble to the constructor of <var>World</var>.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>World (int id)
: _identifier (id), _matter (_identifier)</pre>
</table>
<!-- End Code -->
<p>
It first initializes the <var>_identifier</var> and than <var>_matter</var>. Initializing an object means calling its constructor. The constructor of <var>Matter</var> requires an integer, and that's what we are passing there. We made <var>_matter</var> <var>const</var> for the same reason we made <var>_identifier</var> <var>const</var>. It is never changed during the lifetime of the <var>World</var>. It is initialized in the preamble and never even accessed by anybody. By the way, the double slash <var>//</var> is used for comments. The compiler ignores everything that follows <var>//</var> until the end of line.
And now for the surprise: The order of initialization has <i>nothing to do</i> with the order in the preamble. In fact, if the constructor of the embedded object doesn't require any arguments, it can be omitted from the preamble whatsoever. If no explicit initialization is required, the whole preamble may be omitted. <p>
<p>
Instead, the rule of initialization is:
<!-- Definition -->
<p>
<table border=4 cellpadding=10><tr>
<td bgcolor="#ffffff" class=defTable>
Data members are initialized in the order in which they appear in the class definition.
</table>
<!-- End Definition -->
<p>
Since <var>_identifier</var> appears before <var>_matter</var> in the definition of <var>World</var>, it will be initialized first. That's why we could use its value to in the construction of <var>_matter</var>. The order of embeddings in C++ is as important as the order of statements.
<p>The destruction of embedded objects is guaranteed to proceed in the opposite order of construction. The object that was constructed first will be destroyed last, and so on.
<p>
In the object-oriented argot, object embedding is called the "has-a" relationship. A <var>World</var> has a <var>Matter</var> (remember, we have objectified matter).
<p><img src="has-a.gif" tppabs="http://www.relisoft.com/book/lang/scopes/images/has-a.gif" width=216 height=66 border=0 alt="has-a">
<p class=caption>Figure 4 Graphical representation of the has-a relationship.
<p class=summary>
To summarize, objects of programmer defined types may be embedded as data members in other classes. The constructors for the embeddings are called before the body of the object's constructor is executed (conceptually you may visualize them as being called in the preamble). If these constructors need arguments, they must be passed in the preamble. The order of construction is determined by the order of embeddings. The embeddings are destroyed in the reverse order of construction.
</table>
<!-- End Main Table -->
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -