Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
8:Constants8:Constants
김동원김동원김동원김동원
2003.03.31
Thinking in C++ Page 1
Overview
• Classes
• Volatile
Thinking in C++ Page 2
Class
• Const in classes
–The constructor initializer list
–Constructors for built-in types
• Compile-time constants in classes
–The enum hack in old code
• Const objects & member functions
Thinking in C++ Page 3
Const in classes
• Inside a class, const
–Partially reverts to its meaning in C
– It allocates storage within each object and represents a value that is initialized once and then cannot change
–This is constant for the lifetime of the object
–However, each different object may contain a different value for that constant
• When you create an ordinary (non-static) const inside a class
–You cannot give it an initial value
–This initialization must occur in the constructor, of course, but in a special place in the constructor
Thinking in C++ Page 4
The constructor initializer list
• The constructor initializer list
–A list of constructor calls
� occur after the function argument list a colon, but before the opening brace of the constructor body
–The initialization in the list occurs before any of the main constructor code is executed
–This is the place to put all const initializations
Thinking in C++ Page 5
The constructor initializer list (example)
#include <iostream>using namespace std;class Fred {const int size;
public:Fred(int sz);void print();
};Fred::Fred(int sz) : size(sz) {}void Fred::print() { cout << size << endl; }int main() {Fred a(1), b(2), c(3);a.print(), b.print(), c.print();
}
Thinking in C++ Page 6
Constructors for built-in types
//: C08:BuiltInTypeConstructors.cpp#include <iostream>using namespace std;class B {int i;
public:B(int ii);void print();
};B::B(int ii) : i(ii) {}void B::print() { cout << i << endl; }int main() {B a(1), b(2);float pi(3.14159);a.print(); b.print();cout << pi << endl;
}
Thinking in C++ Page 7
Compile-time constants in classes
• How do you make a compile-time constant inside a class?
–The answer requires the use of an additional keyword which will not be fully introduced until Chapter 10: static
• static
–There’s only one instance, regardless of how many objects of the class are created
–A member of a class which is constant, and which cannot change from one object of the class to another
• Thus, a static const of a built-in type can be treated as a compile-time constant
Thinking in C++ Page 8
Compile-time constants in classes (example)
//: C08:StringStack.cpp// Using static const to create a// compile-time constant inside a class#include <string>#include <iostream>using namespace std;class StringStack {static const int size = 100;const string* stack[size];int index;
public:StringStack();void push(const string* s);const string* pop();
};
Thinking in C++ Page 9
The “enum hack” in old code
• In older versions of C++
–static const was not supported inside classes
–However, people still wanted to do this so a typical solution was to use an untagged enum with no instances
• An enumeration
–must have all its values established at compile time
– Its values are available for constant expressions
Thinking in C++ Page 10
The “enum hack” in old code
//: C08:EnumHack.cpp
#include <iostream>
using namespace std;
class Bunch {
enum { size = 1000 };
int i[size];
};
int main()
{
cout << "sizeof(Bunch) = " << sizeof(Bunch)
<< ", sizeof(i[1000]) = "
<< sizeof(int[1000]) << endl;
}
Thinking in C++ Page 11
const objects & member functions
• A const object
–defined the same for a user-defined type as a built-in type
� const int i = 1;
� const blob b(2);
– It must ensure that no data members of the object are changed during the object’s lifetime
Thinking in C++ Page 12
const objects & member functions
• Class member functions can be made const
– If you declare a member function const, you tell the compiler the function can be called for a const object
– If you try to change any members of the object or call a non-const member function
� Issuing an error message
� Any member function you declare const is guaranteed to behave that way in the definition
–const keyword must be repeated in the definition
– If it attempts to change the member data in any way or to call another member function that is not const, the compiler flags it as an error
Thinking in C++ Page 13
const objects & member functions(example)
//: C08:ConstMember.cppclass X {int i;
public:X(int ii);int f() const;
};X::X(int ii) : i(ii) {}int X::f() const { return i; }int main(){X x1(10);const X x2(20);x1.f();x2.f();
}
Thinking in C++ Page 14
const objects & member functions
• Neither constructors nor destructors
–can be const member functions
� Because they virtually always perform some modificationon the object during initialization and cleanup
Thinking in C++ Page 15
mutable: bitwise vs. logical const
• Bitwise const
–Every bit in the object is permanent, so a bit image of the object will never change
• Logical const
–Although the entire object is conceptually constant, there may be changes on a member-by-member basis
• To change constness
–casting away constness
–use the mutable keyword in the class declaration
� A particular data member may be changed inside a constobject
Thinking in C++ Page 16
mutable: bitwise vs. logical const (example)
//: C08:Castaway.cpp// "Casting away" constnessclass Y {
int i;public:
Y();void f() const;
};Y::Y() { i = 0; }void Y::f() const{
//! i++; // Error -- const member function((Y*)this)->i++; // OK: cast away const-ness// Better: use C++ explicit cast syntax:(const_cast<Y*>(this))->i++;
}int main() {
const Y yy;yy.f(); // Actually changes it!
}
Thinking in C++ Page 17
mutable: bitwise vs. logical const (example)
//: C08:Mutable.cpp// The "mutable" keywordclass Z {
int i;mutable int j;
public:Z();void f() const;
};Z::Z() : i(0), j(0) {}void Z::f() const{
//! i++; // Error -- const member functionj++; // OK: mutable
}int main() {
const Z zz;zz.f(); // Actually changes it!
}
Thinking in C++ Page 18
volatile
• volatile
Thinking in C++ Page 19
volatile
• The syntax of volatile
– identical to that for const
–but volatile means this data may change outside the knowledge of the compiler
• The data is volatile
–The data may have been changed by another process
– It must reread that data rather than optimizing the code to remove what would normally be a redundant read
Thinking in C++ Page 20
volatile (example)
//: C08:Volatile.cpp
// The volatile keyword
class Comm {
const volatile unsigned char byte;
volatile unsigned char flag;
enum { bufsize = 100 };
unsigned char buf[bufsize];
int index;
public:
Comm();
void isr() volatile;
char read(int index) const;
};
Thinking in C++ Page 21
volatile (example)
Comm::Comm() : index(0), byte(0), flag(0) {}// Only a demo; won't actually work// as an interrupt service routine:void Comm::isr() volatile {flag = 0;buf[index++] = byte;// Wrap to beginning of buffer:if(index >= bufsize) index = 0;
}char Comm::read(int index) const{if(index < 0 || index >= bufsize)
return 0;return buf[index];
}
Thinking in C++ Page 22
volatile (example)
int main()
{
volatile Comm Port;
Port.isr(); // OK
//! Port.read(0); // Error, read() not volatile
}