12.6.
static Class Members
It is sometimes
necessary for all the objects of a particular class type to access a global
object. Perhaps a count is needed of how many objects of a particular class
type have been created at any one point in the program, or the global object
may be a pointer to an error-handling routine for the class, or it may be a
pointer to the free-store memory for objects of this class type.
However, making the
object global violates encapsulation: The object exists to support the
implementation of a particular class abstraction. If the object is global,
general user code can modify the value. Rather than defining a generally
accessible global object, a class can define a class
static member
.
Ordinary, nonstatic
data members exist in each object of the class type. Unlike ordinary data
members, a static data member exists independently of any object of its class;
each static data member is an object associated with the class, not with the
objects of that class.
Just as a class may
define shared static data members, it may also define static member functions.
A static member function has no this parameter. It may directly access the
static members of its class but may not directly use the nonstatic members.
Advantages
of Using Class static Members
There are three
advantages to using static members rather than globals:
-
The
name of a static member is in the scope of the class, thereby avoiding
name collisions with members of other classes or global objects.
-
Encapsulation can be enforced. A
static member can be a private member; a global object cannot.
-
It is easy to see by reading the
program that a static member is associated with a particular class. This
visibility clarifies the programmer's intentions.
Defining
static Members
Amember ismade static
by prefixing the member declaration with the keyword static. The static members
obey the normal public/private access rules.
As an example, consider
a simple class intended to represent a bank account. Each account has a balance
and an owner. Each account earns interest monthly, but the interest rate
applied to each account is always the same. We could write this class as
class Account {
public:
// interface functions
here
void applyint() { amount +=
amount * interestRate; }
static double rate() { return
interestRate; }
static void rate(double); //
sets a new rate
private:
std::string owner;
double amount;
static double
interestRate;
static double
initRate();
};
Each object of this
class has two data members: owner and amount. Objects do not have data members
that correspond to static data members. Instead, there is a single interestRate
object that is shared by all objects of type Account.
Using
a Class static Member
A static member can be
invoked directly from the class using the scope operator or indirectly through
an object, reference, or pointer to an object of its class type.
Account ac1;
Account *ac2 = &ac1;
// equivalent ways to call the
static member rate function
double rate;
rate = ac1.rate();
// through an Account object or
reference
rate = ac2->rate();
// through a pointer to an Account
object
rate = Account::rate();
// directly from the class using the scope
operator
As with other members,
a class member function can refer to a class static member without the use of
the scope operator:
class Account {
public:
// interface functions
here
void applyint() { amount +=
amount * interestRate; }
};
Exercises
Section 12.6
Exercise 12.36:
|
What is a static
class member? What are the advantages of static members? How do they differ
from ordinary members?
|
Exercise 12.37:
|
Write your own
version of the Account class.
|
12.6.1.
static Member Functions
Our Account class has
two static member functions named rate, one of which was defined inside the
class. When we define a static member outside the class, we do not respecify
the static keyword. The keyword appears only with the declaration inside the class
body:
void Account::rate(double
newRate)
{
interestRate =
newRate;
}
static
Functions Have No this Pointer
A static member is part
of its class but not part of any object. Hence, a static member function does
not have a this pointer. Referring to this either explicitly or implicitly by
using a nonstatic member is a compile-time error.
Because a static member
is not part of any object, static member functions may not be declared as
const. After all, declaring a member function as const is a promise not to
modify the object of which the function is a member. Finally, static member
functions may also not be declared as virtual. We'll learn about virtual
functions in Section
15.2.4
(p. 566
).
12.6.2.
static Data Members
static data members can
be declared to be of any type. They can be consts, references, arrays, class
types, and so forth.
static data members
must be defined (exactly once) outside the class body. Unlike ordinary data
members, static members are not initialized through the class constructor(s)
and instead should be initialized when they are defined.
Exercises
Section 12.6.1
Exercise 12.38:
|
Define a class named
Foo that has a single data member of type int. Give the class a constructor
that takes an int value and initializes the data member from that value. Give
it a function that returns the value of its data member.
|
Exercise 12.39:
|
Given the class Foo
defined in the previous exercise, define another class Bar with two static
data elements: one of type int and another of type Foo.
|
Exercise 12.40:
|
Using the classes
from the previous two exercises, add a pair of static member functions to
class Bar. The first static, named FooVal, should return the value of class
Bar's static member of type Foo. The second member, named callsFooVal, should
keep a count of how many times xval is called.
|
The best way to ensure
that the object is defined exactly once is to put the definition of static data
members in the same file that contains the definitions of the class noninline
member functions.
static data members are
defined in the same way that other class members and other variables are
defined. The member is defined by naming its type followed by the fully
qualified name of the member.
We might define
interestRate as follows:
// define and initialize static class
member
double Account::interestRate =
initRate();
This statement defines
the static object named interestRate that is a member of class Account and has
type double. Like other member definitions, the definition of a static member
is in class scope once the member name is seen. As a result, we can use the
static member function named initRate directly without qualification as the
initializer for rate. Note that even though initRate is private, we can use
this function to initialize interestRate. The definition of interestRate, like
any other member definition, is in the scope of the class and hence has access
to the private members of the class.
As with any class
member, when we refer to a class static member outside the class body, we must
specify the class in which the member is defined. The static keyword, however,
is used only on the declaration inside the class body. Definitions are not labeled
static.
Integral
const static Members Are Special
Ordinarily, class
static members, like ordinary data members, cannot be initialized in the class
body. Instead, static data members are normally initialized when they are
defined.
One exception to this
rule is that a const static data member of integral type can be initialized
within the class body as long as the initializer is a constant expression:
class Account {
public:
static double rate() { return
interestRate; }
static void rate(double);
// sets a new rate
private:
static
const int period = 30; // interest posted every 30 days
double daily_tbl[period]; // ok:
period is constant expression
};
A const static data
member of integral type initialized with a constant value is a constant
expression. As such, it can be used where a constant expression is required,
such as to specify the dimension for the array member daily_tbl.
When a const static
data member is initialized in the class body, the data member must still be
defined outside the class definition.
由于在类中进行了初始化
When an
initializer is provided inside the class, the definition of the member must not
specify an initial value:
// definition
of static member with no initializer;
// the initial value is specified
inside the class definition
const int Account::period;
static
Members Are Not Part of Class Objects
Ordinary members are
part of each object of the given class. static members exist independently of
any object and are not part of objects of the class type. Because static data
members are not part of any object, they can be used in ways that would be illegal
for nonstatic data members.
As an example, the type
of a static data member can be the class type of which it is a member. A
nonstatic data member is restricted to being declared as a pointer or a
reference to an object of its class:
class Bar {
public:
// ...
private:
static Bar mem1; //
ok
Bar *mem2;
// ok
Bar mem3;
// error
};
Similarly, a static
data member can be used as a default argument:
class Screen {
public:
// bkground refers to the static
member
// declared later in the class
definition
Screen& clear(char =
bkground);
private:
static const char bkground =
'#';
};
A nonstatic data member
may not be used as a default argument because its value cannot be used
independently of the object of which it is a part. Using a nonstatic data
member as a default argument provides no object from which to obtain the
member's value and so is an error.
Exercises
Section 12.6.2
Exercise 12.41:
|
Given the classes Foo
and Bar that you wrote for the exercises to Section
12.6.1
(p. 470
),
initialize the static members of Foo. Initialize the int member to 20 and the
Foo member to 0.
|
Exercise 12.42:
|
Which, if any, of the
following static data member declarations and definitions are errors? Explain
why.
// example.h
class Example {
public:
static double rate =
6.5;
static const int vecSize =
20;
static vector<double>
vec(vecSize);
};
// example.C
#include
"example.h"
double Example::rate;
vector<double>
Example::vec;
|
分享到:
相关推荐
c++ primer plus 答案c++ primer plus 答案c++ primer plus 答案c++ primer plus 答案 c++ primer plus 答案
C++Primer第五版习题答案+详解(完整版) C++Primer第五版习题答案+详解(完整版)
C++Primer Plus第六版的课后题练习题
C++primer 课后答案,习题对帮助记忆、理解很重要。内容高清,全面,带有书签,
C++Primer中文版第5版
C++Primer中文第三版(C++从入门到精通)第一章的读书笔记,主要是C++程序、预处理器指示符、iostream库等的基础知识点读书笔记。
C++ primer Plus的pdf资源
C++ Primer(5e,Addison Wesley,201208).epub 这是老外网站上刚泄露出来的正式版本(绝对的正式版,还有ISBN和出版日期),不是以前网上出现过的草稿 这本书的上一版(第4版)还是2005年的事了 拖了很多年之后,去年...
C++是一门强大、难学、令人痛苦,但又是如此美妙的编程语言,在工业界和学术界都可以使用,《C++ Primer(第5版)》即针对初学者,也同样适用于有一定编程经验的读者,第5版配备了C++11新标准,是C++粉丝们书架上...
锻炼自己的全英文C++ primer第五版电子版,更加适合于有一定代码功底人士阅读,初学者(你要读也很棒棒)阅读难度较大。
该文件是c++ primer第五版本,为中文版本,可以利用该版本学习c++基础知识和c++11的特性
自己看书练习编写的C++ Primer Plus(第6版)课后题答案
C++ Primer第五版 高清扫描pdf,压缩版,下载后解压即可
c++primer第五版中文版课后答案(第12章)pdf格式,真正的c++primer习题集(第五版),用手机拍的,但是每个字都能看的很清楚
C++ Primer 第五版(中文版) 第1~11章课后习题答案(附上代码)
该视频是关于C++ Primer 这本书的猎豹详细视频初级高级讲解 该视频是关于C++ Primer 这本书的猎豹详细视频初级高级讲解 该视频是关于C++ Primer 这本书的猎豹详细视频初级高级讲解 该视频是关于C++ Primer 这本书的...
这个文件是我买的资料。我看过,和C++ primer plus 这本书的课后习题非常吻合。
C++Primer(第4版)_课后习题答案
c++primer第四版练习答案完整版。
c++ primer 第5版 英文版 原版精美排版 mobi格式 kindle直读