eryar

PipeCAD - Plant Piping Design Software.
RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
posts - 603, comments - 590, trackbacks - 0, articles - 0

Hide Implementation Classes

Posted on 2013-09-28 22:32 eryar 阅读(3510) 评论(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,即在头文件中也不出现。我将在下一节中讲到怎样来实现。

 

Feedback

# re: Hide Implementation Classes  回复  更多评论   

2013-09-29 10:58 by 春秋十二月
这里嵌套类FireParticle的变量并没有被隐藏

# re: Hide Implementation Classes  回复  更多评论   

2013-09-29 17:46 by eryar
如果给了头文件,是可以看到源代码,但是即使看到代码,在程序的其他地方也不能定义一个FireParticle类的对象了。
我是这么理解的。。。@ 春秋十二月

# re: Hide Implementation Classes[未登录]  回复  更多评论   

2013-09-30 02:03 by 春秋十二月
@eryar
虽为私有,但暴露了它的定义,比如一个非正常情况#define private public,那么sizeof(Fireworks::FireParticle)是定义了的。

# re: Hide Implementation Classes  回复  更多评论   

2013-09-30 17:44 by eryar
#define private public这招太狠了……
这样的话FireParticle是没有达到隐藏的效果。
那本书里面这里的隐藏是相对于private而言的,
@春秋十二月

# re: Hide Implementation Classes  回复  更多评论   

2013-10-06 20:11 by ccsdu2009
你这个不如impl!

# re: Hide Implementation Classes  回复  更多评论   

2013-10-09 19:15 by eryar
什么是impl?
还请指教
@ccsdu2009

# re: Hide Implementation Classes  回复  更多评论   

2013-10-29 11:18 by Jayden Shui
应该是pimpl吧。该书3.1.1.

# re: Hide Implementation Classes  回复  更多评论   

2013-10-29 18:38 by eryar
哦,谢谢。。。
:-)
@Jayden Shui

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理