📄 7store.html
字号:
<html>
<head>
<title>Store</title>
<meta name="description" content="Implementation of variable store in C++">
<meta name="keywords" content="calculator, memory, symbol, variable, storage, implementation">
<link rel="stylesheet" href="../../rs.css">
</head>
<body background="../../images/margin.gif" bgcolor="#FFFFDC">
<!-- Main Table -->
<table cellpadding="6">
<tr>
<td width="78">
<td>
<h3>Store</h3>
<p class=topics>Forward declarations.
<p>Our calculator can deal with symbolic variables. The user creates a variable by inventing a name for it and then using it in arithmetic operations. Every variable has to be initialized梐ssigned a value in an assignment expression梑efore it can be used in evaluating other expressions. To store the values of user defined variables our calculator will need some kind of "memory." We will create a class <var>Store</var> that contains a fixed number, <var>size</var>, of memory cells. Each cell can store a value of the type double. The cells are numbered from zero to <var>size</var>-1. Each cell can be in either of two states梪ninitialized or initialized.
<!-- Code --><table width="100%" cellspacing=10><tr> <td class=codetable>
<pre>enum { stNotInit, stInit };
</pre></table><!-- End Code --><p>The association between a symbolic name梐 string梐nd the cell number is handled by the symbol table. For instance, when the user first introduces a given variable, say <i>x</i>, the string "x" is added to the symbol table and assigned an integer, say 3. From that point on, the value of the variable <i>x</i> will be stored in cell number 3 in the <var>Store</var> object.
<p>We would also like to pre-initialize the symbol table and the store with some useful constants like <i>e</i> (the base of natural logarithms) and <i>pi</i> (the ratio of the circumference of a circle to its diameter). We would like to do it in the constructor of <var>Store</var>, therefore we need to pass it a reference to the symbol table. Now here抯 a little snag: We want to put the definition of the class <var>Store</var> in a separate header file, <b><i>store.h</i></b>. The definition of the class <var>SymbolTable</var> is in a different file, <b><i>symtab.h</i></b>. When the compiler is looking at the declaration of the constructor of <var>Store</var>
<!-- Code --><table width="100%" cellspacing=10><tr> <td class=codetable>
<pre> Store (int size, SymbolTable & symTab);
</pre></table><!-- End Code --><p>it has no idea what <var>SymbolTable</var> is. The simple-minded solution is to include the file <b><i>symtab.h</i></b> in <b><i>store.h</i></b>. There is nothing wrong with doing that, except for burdening the compiler with the processing of one more file whenever it is processing <b><i>symtab.h</i></b> or any file that includes it. In a really big project, with a lot of header files including one another, it might become a real headache. If you are using any type of dependency checker, it will assume that a change in <b><i>symtab.h</i></b> requires the recompilation of all the files that include it directly or indirectly. In particular, any file that includes <b><i>store.h</i></b> will have to be recompiled too. And all this unnecessary processing just because we ed to let the compiler know that <var>SymbolTable</var> is a name of a class? Why don抰 we just say that? Indeed, the syntax of such a <b><i>forward declaration</i></b> is:
<!-- Code --><table width="100%" cellspacing=10><tr> <td class=codetable>
<pre>class SymbolTable;
</pre></table><!-- End Code --><p>As long as we are <i>only</i> using pointers or references to <var>SymbolTable</var>, this will do. We don抰 need to include <b><i>symtab.h</i></b>. On the other hand, a forward declaration would not be sufficient if we wanted to call any of the methods of <var>SymbolTable</var> (including the constructor or the destructor) or if we tried to embed or inherit from <var>SymbolTable</var>.
<!-- Code --><table width="100%" cellspacing=10><tr> <td class=codetable>
<pre>class SymbolTable; // forward declaration
class Store
{
public:
Store (int size, SymbolTable & symTab);
~Store ()
{
delete []_cell;
delete []_status;
}
bool IsInit (int id) const
{
return (id < _size && _status [id] != stNotInit);
}
double Value (int id) const
{
assert (IsInit (id));
return _cell [id];
}
void SetValue (int id, double val)
{
if (id < _size)
{
_cell [id] = val;
_status [id] = stInit;
}
}
private:
int _size;
double * _cell;
unsigned char * _status;
};
</pre></table><!-- End Code -->
<var><p>Store</var> contains two arrays. The array of cells and the array of statuses (initialized/uninitialized). They are initialized in the constructor and deleted in the destructor. We also store the size of these arrays (it's used for error checking). The client of <var>Store</var> can check whether a given cell has been initialized, get the value stored there, as well as set (and initialize) this value.
<!-- Sidebar -->
<table width="100%" border=0 cellpadding=5><tr>
<td width=10>
<td bgcolor="#cccccc" class=sidebar>
<p>Why am I using two arrays instead of a single array of two-field objects? I could have defined a class <var>Cell</var>
<!-- Code --><table width="100%" cellspacing=10><tr> <td class=codetable>
<pre>class Cell
{
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -