`
shi5jin
  • 浏览: 38043 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

为什么编译要花这么长的时间?

阅读更多

    你的编译器可能有问题。也许它太老了,也许你安装它的时候出了错,也许你用的计算机已经是个古董。在诸如此类的问题上,我无法帮助你。 

    但是,这也是很可能的:你要编译的程序设计得非常糟糕,以至于编译器不得不检查数以百计的头文件和数万行代码。理论上来说,这是可以避免的。如果这是你购 买的库的设计问题,你对它无计可施(除了换一个更好的库),但你可以将你自己的代码组织得更好一些,以求得将修改代码后的重新编译工作降到最少。这样的设 计会更好,更有可维护性,因为它们展示了更好的概念上的分离。 

    看看这个典型的面向对象的程序例子: 

        class Shape {
    
    public:     // 使用Shapes的用户的接口
    
        virtual void draw() const;
            virtual void rotate(int degrees);
            // ...
        protected:  // common data (for implementers of Shapes)
            Point center;
            Color col;
            // ...
        }; 

        class Circle : public Shape {
        public: 
            void draw() const;
            void rotate(int) { }
            // ...
        protected:
            int radius;
            // ...
        };

        class Triangle : public Shape {
        public: 
            void draw() const;
            void rotate(int);
            // ...
        protected:
            Point a, b, c;
            // ...
        }; 

    设计思想是,用户通过Shapepublic接口来操纵它们,而派生类(例如CircleTriangle)的实现部分则共享由protected成员表现的那部分实现(implementation)。

    然而,这个简单的设计理念里却隐含着三个严重的问题:

    • 这不是一件容易的事情:确定哪些实现部分是对所有的派生类都有用的,并将之共享出来。因此,与public接口相比,protected成员往往要做多得多的改动。举例来说,虽然理论上“中心”(center)对所有的图形都是一个有效的概念,但当你要维护一个三角形的“中心”的时候,是一件非常麻烦的事情——对于三角形,当且仅当它确实被需要的时候,计算这个中心才是有意义的。 
    • protected成员很可能要依赖于实现部分的细节,而Shape的用户(译注:user此处译为用户,指使用Shape类的代码,下同)却不见得必须依赖它们。举例来说,很多(大多数?)使用Shape的代码在逻辑上是与“颜色”无关的,但是由于Shape中“颜色”这个定义的存在,却可能需要一堆复杂的头文件,来结合操作系统的颜色概念。 
    • protected部分发生了改变时,使用Shape的代码必须重新编译——即使只有派生类的实现部分才能够访问protected成员。

    于是,基类中的“实现相关的信息”(information helpful to implementers)对用户来说变成了象接口一样敏感的东西,它的存在导致了实现部分的不稳定,用户代码的无谓的重编译(当实现部分发生改变时),以及将头文件无节制地包含进用户代码中(因为“实现相关的信息”需要它们)。有时这被称为“脆弱的基类问题”(brittle base class problem) 

    一个很明显的解决方案就是,忽略基类中那些象接口一样被使用的“实现相关的信息”。换句话说,使用接口,纯粹的接口。也就是说,用抽象基类的方式来表示接口: 

        class Shape {
        public:     //使用Shapes的用户的接口
            virtual void draw() const = 0;
            virtual void rotate(int degrees) = 0;
            virtual Point center() const = 0;
            // ...
            // 没有数据
        };

        class Circle : public Shape {
        public: 
            void draw() const;
            void rotate(int) { }
            Point center() const { return center; }
            // ...
        protected:
            Point cent;
            Color col;
            int radius;
            // ...
        }; 

        class Triangle : public Shape {
        public: 
            void draw() const;
            void rotate(int);
            Point center() const;
            // ...
        protected:
            Color col;
            Point a, b, c;
            // ...
        };   

    现在,用户代码与派生类的实现部分的变化之间的关系被隔离了。我曾经见过这种技术使得编译的时间减少了几个数量级。 

    但是,如果确实存在着对所有派生类(或仅仅对某些派生类)都有用的公共信息时怎么办呢?可以简单把这些信息封装成类,然后从它派生出实现部分的类: 

    class Shape {
    public:     //使用Shapes的用户的接口
        virtual void draw() const = 0;
        virtual void rotate(int degrees) = 0;
        virtual Point center() const = 0;
        // ...
        // no data
    }; 

    struct Common {
        Color col;
        // ...
    };       

    class Circle : public Shape, protected Common {
    public: 
        void draw() const;
        void rotate(int) { }
        Point center() const { return center; }
        // ...
    protected:
        Point cent;
        int radius;
    }; 

    class Triangle : public Shape, protected Common {
    public: 
        void draw() const;
        void rotate(int);
        Point center() const;
        // ...
    protected:
        Point a, b, c;
    }; 

原文地址:http://www.research.att.com/~bs/bs_faq2.html#abstract-class

分享到:
评论

相关推荐

    编译原理课程设计 花好长时间做的

    自己做的编译原理课程设计,希望对大家帮助

    Java快速编译工具

    Java快速编译工具,解救你于繁琐的命令行编译之中! ...这个程序花了我好长时间才打成安装包,但是可能会有点问题,欢迎大家批评指正。 最后,也欢迎大家对本程序提出宝贵意见,支持本程序的更新。

    C++风格与技巧

    为什么编译要花这么长的时间?为什么一个空类的大小不为0?我必须在类声明处赋予数据吗?为什么成员函数默认不是virtual的?为什么析构函数默认不是virtual的?为什么不能有虚拟构造函数?为什么重载在继承类中不...

    mongo c++ driver 编译步骤

    mongo c++ driver 编译步骤代码编译步骤,由于我根据官方提供的步骤,花了很长的时间去探索,最后终于成功,作出总结,此文档完全自己亲自编写,希望能给大家带来方便。

    DePB 针对PowerBuilder语言编写的程序进行反编译的工具

    [关于DePB] DePB是一个针对PowerBuilder语言编写的程序进行反编译的工具,目前v1.0版还只是一个未完成的作品。... 希望在未来的不长时间内,我能够重新抽出时间完善这个作品。 2003-05-30 夜

    编译过的gdal\geos\proj4库

    我自己编译的gdal库,geos和proj4库,可以处理矢量数据,遥感影像 的坐标转换,因为自己先分别编译三个库函数,然后再进行集成编译,加上一些整理思绪花了很长时间才搞出来,如果分高的话可以参考我相关资源,有geos...

    win7下编译ffmpeg所需安装包(2016.12最新版)

    在描述中提到,博主花了很长时间才成功编译出FFmpeg,并且还有待改进的地方。可能遇到的问题包括但不限于依赖库的版本兼容性问题、编译选项设置错误、缺少必要的Windows SDK或库文件,以及配置脚本中的Windows路径...

    以前在学习Delphi的时候曾经花了很长时间编写这个东西,现在在项目中又重新用到了这个问题

    以前在学习Delphi的时候曾经花了很长时间编写这个东西,现在在项目中又重新用到了这个问题,于是把以前的代码翻出来重新修正、编译,感觉还不错,将Excel导入Access的功能也是挺实用的,在D7下完成编译,注意,因每...

    程序设计语言之编译原理

    如果你对编译原理不是很懂且不想花很长时间去研究,你可以下载此文档。

    Funkeys github SDK 全

    包括所有子模块 无需编译clone ,避免很长时间在git clone ,花了我3天的时间终于clone下来了。。。。。。。。

    简易定时器1、独有三种设置提醒时间的方式,令该程序更方便易用。

    和定时器运行了多长时间。 7、附带系统锁定功能,用户离开计算机时可以暂时锁定计算机。 8、软件连安装程序小于100KB,方便网友下载使用。 ★新手上路: 如果你是新使用定时器的用户,你可以尝试用鼠标双击或...

    c语言浪漫烟花源码.rar

    vs2017环境下成功编译,vc6.0编译不通过 #include "stdafx.h" #include #include #include #include <time.h> // 使用该计时器必须包含的文件 #pragma comment ( lib, "Winmm.lib" ) ...

    史上最完美的Qwt6.1.0傻瓜式安装教程(可以集成到QTC的Designer里面)

    3、安装这个东西要多长时间? 答:如果你动作快,20分钟以内肯定能搞定,因为我把QtCreator都给你编译好了,帮你节省了一个小时时间。 4、安装这个东西的成功率有多高? 答:即使你利用《详细安装版》安装不...

    学习单片机的心得体会

    * 问题2:我计划花多长时间学习PIC单片机? 回答:学习PIC单片机的时间取决于你的学习速度和努力程度,通常需要数周到数月的时间。 * 问题3:我要以哪个型号的PIC单片机入门? 回答:可以选择PIC16F877A作为入门的...

    C ++ 需要注意的问题 FAQ

    **为什么编译要花这么长的时间?** - **原因分析**: - **复杂的代码结构**:C++ 允许复杂的类层次结构、模板元编程等特性,这些都会增加编译时间。 - **预处理器的使用**:C++ 使用了大量的宏和预处理器指令,...

    游戏陪练,预约交友,语音聊天双端APP源代码+编译说明

    1.游戏陪练:可以选择当前流行的游戏内容,选择游戏神和职业玩家陪练,也可以请...本来不想放出来的毕竟我也花了不少,买的时候以为是H5+app呢,搭建一下才发现只能编译app对接, api.php route.php 这两个文件已解密

    报告-编译原理-实验1 词法分析.doc

    2. **实验时长**:实验总共需要4学时,确保学生有足够的时间来完成设计、编码和测试工作。 3. **实验内容**:首先,基于给定的语言规则构造一个状态转换图,这个图用于识别单词的集合。然后,编写词法分析器的程序...

    Bjarne Stroustrup的FAQ:C++的风格与技巧

    ##### (2) 为什么编译要花这么长的时间? C++编译时间较长的原因主要有两个方面:一是因为C++是一种静态类型语言,编译器需要进行大量的类型检查;二是现代C++程序往往包含了大量模板和泛型代码,这些都需要在编译...

    WINCE6.0环境下DDRAW动态图片演示程序(DirectDraw)

    花了好长时间,终于将DDRAW编译成功了,看到图片闪烁,很有成就感... 附件绝对可以编译通过,根目录下的test.exe程序可以直接运行; 注意事项:  1.一定要在wince 6.0及vs2005编译下,其它环境下我不确定能不能编译...

    borland c++ V4.5

    一款用于ucos-ii的编译软件,...本人也是花很长时间才找到资源的,现在上传供学习uCOS的爱好者们使用。 解压后打开bc文件夹,找到INSTALL.EXE双击运行即可按照安装提示安装。WIN 7系统似乎安装有问题,xp可以正常安装。

Global site tag (gtag.js) - Google Analytics