Posted on 2013-09-28 22:32
eryar 閱讀(3603)
評論(8) 編輯 收藏 引用
Hide Implementation Classes
eryar@163.com
摘要:很多程序員都用過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
注意到在類FireParticle中我并沒有使用getter/setter。只要你愿意,當然也可以這樣做。但是也不是非常必要這么做,因為公有的接口是不能訪問這個類的。有些工程師也比較喜歡使用struct來代替class,to reflect that the structure is a Plain Old Data(POD) type。
當然,你可能也想過隱藏類FireParticle,即在頭文件中也不出現。我將在下一節中講到怎樣來實現。