Hide Implementation Classes
摘要:很多程序员都用过private来隐藏函数和成员变量,实际上有些类也是可以被隐藏起来的。本文是对《API Design for C++》中2.2.5的翻译,若不不当之处,欢迎指出。
关键字:API Design for C++, Hide Classes
除了可以隐藏类的变量与方法之外,还可以隐藏任意单纯实现细节的类。很多程序员都用过隐藏方法和变量,但是好多也好像忘记了并不是所有的类都是公有的。实际上,有些类只在你的实现中需要,而不应该作为公开的接口暴露出来。
例如,考虑一个简单的烟花(Fireworks)类:一个接口可以用来指定烟花在屏幕上位置,控制烟花的颜色、速度和烟花颗粒(particle)的数量。明显地,这个API就需要对烟花的每个颗粒进行追踪,以便于在每帧更新颗粒的位置。这暗示着需要引入一个用来保存每个颗粒状态的类FireParticle,但是这个API的用户并不需要访问这个类,它只在实现API时才需要。这样的类就可以设置为私有(private),即作为类Fireworks私有的部分。代码如下所示:
1
///
-*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: t -*-
2 ///
3 /// \file fireworks.h
4 /// \author Martin Reddy
5 /// \brief An illustration of using private classes.
6 ///
7 /// Copyright (c) 2010, Martin Reddy. All rights reserved.
8 /// Distributed under the X11/MIT License. See LICENSE.txt.
9 /// See http://APIBook.com/ for the latest version.
10 ///
11
12 #ifndef FIREWORKS_H
13 #define FIREWORKS_H
14
15 #include < vector >
16
17 namespace apibook {
18
19 ///
20 /// A simple fireworks particle system, used to demonstrate
21 /// the use of private classes to hide implementation state.
22 ///
23 class Fireworks
24 {
25 public :
26 Fireworks();
27
28 /// Set the (x, y) origin of the fireworks effect
29 void SetOrigin( double x, double y);
30 /// Set the RGB color (0..1) for each particle
31 void SetColor( float r, float g, float b);
32 /// Set the gravity acting on each particle (meters/sec)
33 void SetGravity( float g);
34 /// Set the speed of the particle simulation
35 void SetSpeed( float s);
36 /// Set the number of particles in the simulation
37 void SetNumberOfParticles( int num);
38
39 /// Start (or continue) the simulation
40 void Start();
41 /// Stop the simulation
42 void Stop();
43 /// Advance the simulation by dt seconds
44 void NextFrame( float dt);
45
46 private :
47 // FireParticle represents internal hidden state
48 // (You could also forward declare this class and
49 // only provide the definition in the .cpp file.)
50 class FireParticle
51 {
52 public :
53 double mX, mY;
54 double mVelocityX, mVelocityY;
55 double mAccelerationX, mAccelerationY;
56 double mLifeTime;
57 };
58
59 double mOriginX, mOriginY;
60 float mRed, mGreen, mBlue;
61 float mGravity;
62 float mSpeed;
63 bool mIsActive;
64 std::vector < FireParticle *> mParticles;
65 };
66
67 }
68
69 #endif
70
2 ///
3 /// \file fireworks.h
4 /// \author Martin Reddy
5 /// \brief An illustration of using private classes.
6 ///
7 /// Copyright (c) 2010, Martin Reddy. All rights reserved.
8 /// Distributed under the X11/MIT License. See LICENSE.txt.
9 /// See http://APIBook.com/ for the latest version.
10 ///
11
12 #ifndef FIREWORKS_H
13 #define FIREWORKS_H
14
15 #include < vector >
16
17 namespace apibook {
18
19 ///
20 /// A simple fireworks particle system, used to demonstrate
21 /// the use of private classes to hide implementation state.
22 ///
23 class Fireworks
24 {
25 public :
26 Fireworks();
27
28 /// Set the (x, y) origin of the fireworks effect
29 void SetOrigin( double x, double y);
30 /// Set the RGB color (0..1) for each particle
31 void SetColor( float r, float g, float b);
32 /// Set the gravity acting on each particle (meters/sec)
33 void SetGravity( float g);
34 /// Set the speed of the particle simulation
35 void SetSpeed( float s);
36 /// Set the number of particles in the simulation
37 void SetNumberOfParticles( int num);
38
39 /// Start (or continue) the simulation
40 void Start();
41 /// Stop the simulation
42 void Stop();
43 /// Advance the simulation by dt seconds
44 void NextFrame( float dt);
45
46 private :
47 // FireParticle represents internal hidden state
48 // (You could also forward declare this class and
49 // only provide the definition in the .cpp file.)
50 class FireParticle
51 {
52 public :
53 double mX, mY;
54 double mVelocityX, mVelocityY;
55 double mAccelerationX, mAccelerationY;
56 double mLifeTime;
57 };
58
59 double mOriginX, mOriginY;
60 float mRed, mGreen, mBlue;
61 float mGravity;
62 float mSpeed;
63 bool mIsActive;
64 std::vector < FireParticle *> mParticles;
65 };
66
67 }
68
69 #endif
70
注意到在类FireParticle中我并没有使用getter/setter。只要你愿意,当然也可以这样做。但是也不是非常必要这么做,因为公有的接口是不能访问这个类的。有些工程师也比较喜欢使用struct来代替class,to reflect that the structure is a Plain Old Data(POD) type。
当然,你可能也想过隐藏类FireParticle,即在头文件中也不出现。我将在下一节中讲到怎样来实现。
PDF Version: Hide Implementation Classes