??xml version="1.0" encoding="utf-8" standalone="yes"?>无码人妻久久一区二区三区免费,久久久亚洲欧洲日产国码是AV,国产精品无码久久综合http://www.shnenglu.com/robinson119/archive/2007/10/26/35196.html宝杉宝杉Fri, 26 Oct 2007 00:31:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/10/26/35196.htmlhttp://www.shnenglu.com/robinson119/comments/35196.htmlhttp://www.shnenglu.com/robinson119/archive/2007/10/26/35196.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/35196.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/35196.html 

1、什么是const?
   常类型是指用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。(当然Q我们可以偷梁换p行更斎ͼQ?/p>

2、ؓ什么引入constQ?br>  const 推出的初始目的,正是Z取代预编译指令,消除它的~点Q同时承它的优炏V?/p>

3、cons有什么主要的作用Q?br>   Q?Q可以定义const帔RQ具有不可变性?br>        例如Q?br>             const int Max=100;
             int Array[Max];       
   Q?Q便于进行类型检查,使编译器对处理内Ҏ更多了解Q消除了一些隐患?br> 例如Q?br>             void f(const int i) { .........}
        ~译器就会知道i是一个常量,不允怿改;
   Q?Q可以避免意义模p的数字出现Q同样可以很方便地进行参数的调整和修攏V?br>        同宏定义一P可以做到不变则已Q一变都变!如(1Q中Q如果想修改Max的内容,只需要:const int Max=you want;卛_Q?br>   Q?Q可以保护被修饰的东西,防止意外的修改,增强E序的健壮性?br>        q是上面的例子,如果在函C内修改了iQ编译器׃报错Q?br>        例如Q?
             void f(const int i) { i=10;//error! }
    (5) 为函数重载提供了一个参考?br>         class A
         {
           ......
           void f(int i)       {......} file://一个函?br>           void f(int i) const {......} file://?/font>一个函数的重蝲
            ......
          };
     (6) 可以节省I间Q避免不必要的内存分配?br>         例如Q?br>              #define PI 3.14159         file://?/font>量宏
              const doulbe  Pi=3.14159;  file://?/font>时ƈ未将Pi攑օROM?br>              ......
              double i=Pi;               file://?/font>时ؓPi分配内存Q以后不再分配!
              double I=PI;               file://~?/font>译期间进行宏替换Q分配内?br>              double j=Pi;               file://?/font>有内存分?br>              double J=PI;               file://?/font>q行宏替换,又一ơ分配内存!
         const定义帔R从汇~的角度来看Q只是给Z对应的内存地址Q而不是象#define一L出的是立xQ所以,const定义的常量在E序q行q程中只有一份拷贝,?define定义的常量在内存中有若干个拷贝?br>     Q?Q?提高了效率?br>           ~译器通常不ؓ普通const帔R分配存储I间Q而是它们保存在W号表中Q这使得它成Z个编译期间的帔RQ没有了存储与读内存的操作,使得它的效率也很高?/p>

3、如何用constQ?br>   Q?Q修C般常?br>     一般常量是指简单类型的帔R。这U常量在定义Ӟ修饰Wconst可以用在cd说明W前Q也可以用在cd说明W后?br>       例如Q?nbsp; 
           int const x=2;  或  const int x=2;
   Q?Q修饰常数组
       定义或说明一个常数组可采用如下格式:
       int const a[5]={1, 2, 3, 4, 5}; 
         const int a[5]={1, 2, 3, 4, 5};
   Q?Q修饰常对象
      常对象是指对象常量,定义格式如下Q?br>  class A;
       const A a;
         A const a;
      定义常对象时Q同栯q行初始化,q且该对象不能再被更斎ͼ修饰Wconst可以攑֜cd后面Q也可以攑֜cd前面。 
   Q?Q修饰常指针
        const int *A;        file://const修饰指向的对象,A可变QA指向的对象不可变
        int const *A;       file://const修饰指向的对象,A可变QA指向的对象不可变
        int *const A;       file://const修饰指针AQ?nbsp;    A不可变,A指向的对象可?
        const int *const A;  file://?/font>针A和A指向的对象都不可?br>   Q?Q修饰常引用
        使用const修饰W也可以说明引用Q被说明的引用ؓ常引用,该引用所引用的对象不能被更新。其定义格式如下Q?br>       const double & v;
  Q?Q修饰函数的常参?br>        const修饰W也可以修饰函数的传递参敎ͼ格式如下Q?br>        void Fun(const int Var);
        告诉~译器Var在函C中的无法改变Q从而防止了使用者的一些无意的或错误的修改?nbsp;   
   Q?Q修饰函数的q回|
        const修饰W也可以修饰函数的返回|是返回g可被改变Q格式如下:
            const int Fun1();
            const MyClass Fun2();
   Q?Q修饰类的成员函敎ͼ
        const修饰W也可以修饰cȝ成员函数Q格式如下:
            class ClassName
     {
             public:
                  int Fun() const;
                    .....
             }Q?br>        q样Q在调用函数Fun时就不能修改c里面的数据
    Q?Q在另一q接文g中引用const帔R
         extern const int i;     file://?/font>的引用
         extern const int j=10;  file://?/font>误!帔R不可以被再次赋?br>    另外Q还要注意,帔R必须初始化!
         例如Q?br>             const int i=5; 

4、几点值得讨论的地方:
   Q?QconstI竟意味着什么?
        说了q么多,你认为const意味着什么?一U修饰符Q接口抽象?一U新cdQ?br>        也许都是Q在Stroustup最初引入这个关键字Ӟ只是为对象放入ROM做出了一U可能,对于const对象QC++既允许对其进行静态初始化Q也允许对他q行动态初始化。理想的const对象应该在其构造函数完成之前都是可写的Q在析够函数执行开始后也都是可写的Q换句话_const对象h从构造函数完成到析够函数执行之前的不变性,如果q反了这条规则,l果都是未定义的Q虽然我们把const攑օROM中,但这q不能够保证const的Q何Ş式的堕落Q我们后面会l出具体的办法。无论const对象被放入ROM中,q是通过存储保护机制加以保护Q都只能保证Q对于用戯言q个对象没有改变。换句话_废料攉器(我们以后会详l讨论,q就一W带q)或数据库pȝ对一个const的修Ҏ没有Q何问题?br>   Q?Q位元const V.S. 抽象const?
        对于关键字const的解释有好几U方式,最常见的就是位元const ?抽象const。下面我们看一个例子:
        class A
        {
         public:
               ......
               A f(const A& a);
               ......
         };
         如果采用抽象constq行解释Q那是f函数不会L变所引用对象的抽象|如果采用位元constq行解释Q那成了f函数不会L变所引用对象的Q何位元?br>         我们可以看到位元解释正是c++对const问题的定义,const成员函数不被允许修改它所在对象的M一个数据成员?br>         Z么这样呢Q因Z用位元const?个好处:
         最大的好处是可以很Ҏ地检到q反位元const规定的事Ӟ~译器只用去L有没有对数据成员的赋值就可以了。另外,如果我们采用了位元constQ那么,对于一些比较简单的const对象Q我们就可以把它安全的放入ROM中,对于一些程序而言Q这无疑是一个很重要的优化方式。(关于优化处理Q我们到时候专门进行讨论)
         当然Q位元const也有~点Q要不然Q抽象const也就没有产生的必要了?br>         首先Q位元const的抽象性比抽象const的别更低!实际上,大家都知道,一个库接口的抽象性别越低,使用q个库就困难?br>         其次Q用位元const的库接口会暴露库的一些实现细节,而这往往会带来一些负面效应。所以,在库接口和程序实现细节上Q我们都应该采用抽象const?br>         有时Q我们可能希望对const做出一些其它的解释Q那么,p注意了,目前Q大多数对const的解释都是类型不安全的,q里我们׃举例子了Q你可以自己考虑一下,MQ我们尽量避免对const的重新解释?br>   Q?Q放在类内部的常量有什么限Ӟ
        看看下面q个例子Q?br>        class A
        {
         private:
           const int c3 = 7;           // ???
       static int c4 = 7;          // ???
       static const float c5 = 7;  // ???
          ......
  };
         你认Z面的3句对吗?呵呵Q都不对Q用这U类内部的初始化语法的时候,帔R必须是被一个常量表辑ּ初始化的整型或枚丄型,而且必须是static和const形式。这昄是一个很严重的限Ӟ
         那么Q我们的标准委员会ؓ什么做q样的规定呢Q一般来_cd一个头文g中被声明Q而头文g被包含到许多互相调用的单元去。但是,Z避免复杂的编译器规则QC++要求每一个对象只有一个单独的定义。如果C++允许在类内部定义一个和对象一样占据内存的实体的话Q这U规则就被破坏了?br>    Q?Q如何初始化cd部的帔RQ?br>         一U方法就是static ?const q用Q在内部初始化,如上面的例子Q?br>         另一个很常见的方法就是初始化列表Q?br>         class A
         {
          public:
                A(int i=0):test(i) {}
          private:
                const int i;
          }Q?br>          q有一U方式就是在外部初始化,例如Q?br>         class A
         {
          public:
                A() {}
          private:
                static const int i;  file://?/font>意必L静态的Q?br>          }Q?br>          const int A::i=3;
     Q?Q常量与数组的组合有什么特D吗Q?br>          我们l出下面的代码:
           const int size[3]={10,20,50};
           int array[size[2]];
           有什么问题吗Q对了,~译通不q!Z么呢Q?br>           const可以用于集合Q但~译器不能把一个集合存攑֜它的W号表里Q所以必d配内存。在q种情况下,const意味着“不能改变的一块存?#8221;。然而,其值在~译时不能被使用Q因为编译器在编译时不需要知道存储的内容。自Ӟ作ؓ数组的大就不行了:Q?br>         你再看看下面的例子:
          class A
         {
          public:
                A(int i=0):test[2]({1,2}) {} file://?/font>认ؓ行吗Q?br>          private:
                const int test[2];
          }Q?br>         vc6下编译通不q,Z么呢Q?br>         关于q个问题Q前些时_njboy问我是怎么回事Q我反问他:“你认为呢Q?#8221;他想了想Q给Z一下解释,大家可以看看Q我们知道编译器堆初始化列表的操作是在构造函C内,昑ּ调用可用代码之前Q初始化的次序依据数据声明的ơ序。初始化时机应该没有什么问题,那么只有是~译器对数组做了什么手脚!其实做什么手脚,我也不知道,我只好对他进行猜:~译器搜索到test发现是一个非静态的数组Q于是,Z分配内存I间Q这里需要注意了Q它应该是一下分配完Qƈ非先分配test[0],然后利用初始化列表初始化Q再分配test[1],q就D数组的初始化实际上是赋|然而,帔R不允许赋|所以无法通过?br>        呵呵Q看了这一D冠冕堂皇的话,真让我笑MQnjboy别怪我揭你短呀Q)我对此的解释是这LQC++标准有一个规定,不允许无序对象在cd部初始化Q数l显然是一个无序的Q所以这L初始化是错误的!对于他,只能在类的外部进行初始化Q如果想让它通过Q只需要声明ؓ静态的Q然后初始化?br>         q里我们看到Q常量与数组的组合没有什么特D!一切都是数l惹的祸Q?br>   Q?Qthis指针是不是constcd的?
        this指针是一个很重要的概念,那该如何理解她呢Q也许这个话题太大了Q那我们~小一些:this指针是个什么类型的Q这要看具体情况Q如果在非const成员函数中,this指针只是一个类cd的;如果在const成员函数中,this指针是一个constcȝ型的Q如果在volatile成员函数?this指针是一个volatilecȝ型的?br>   Q?Qconst到底是不是一个重载的参考对象?
        先看一下下面的例子Q?br>        class A
         {
           ......
           void f(int i)       {......} file://一个函?br>           void f(int i) const {......} file://?/font>一个函数的重蝲
            ......
          };
        上面是重载是没有问题的了Q那么下面的呢?
         class A
         {
           ......
           void f(int i)       {......} file://一个函?br>           void f(const int i) {......} file://Q?Q?Q?/font>
            ......
         };
         q个是错误的Q编译通不q。那么是不是说明内部参数的const不予重蝲呢?再看下面的例子:
        class A
         {
           ......
           void f(int& )       {......} file://一个函?br>           void f(const int& ) {......} file://Q?Q?Q?/font>
            ......
         };
         q个E序是正的Q看来上面的l论是错误的。ؓ什么会q样呢?q要涉及到接口的透明度问题。按g递时Q对用户而言Q这是透明的,用户不知道函数对形参做了什么手脚,在这U情况下q行重蝲是没有意义的Q所以规定不能重载!当指针或引用被引入时Q用户就会对函数的操作有了一定的了解Q不再是透明的了Q这旉载是有意义的Q所以规定可以重载?br>   Q?Q什么情况下为const分配内存Q?br>        以下是我惛_的可能情况,当然Q有的编译器q行了优化,可能不分配内存?br>        A、作为非静态的cL员时Q?br>        B、用于集合时Q?br>        C、被取地址Ӟ
        D、在main函数体内部通过函数来获得值时Q?br>        E、const?class或struct有用户定义的构造函数、析构函数或基类Ӟ?br>        F、当const的长度比计算机字长还长时Q?br>        G、参C的constQ?br>        H、用了extern时?br>        不知道还有没有其他情况,Ƣ迎高手指点Q)       
   Q?Q时变量到底是不是帔RQ?br>        很多情况下,~译器必d立时对象。像其他M对象一P它们需要存储空间而且必须被构造和删除。区别是我们从来看不到编译器负责军_它们的去留以及它们存在的l节。对于C++标准草案而言Q时对象自动地成ؓ帔R。因为我们通常接触不到临时对象Q不能用与之相关的信息Q所以告诉时对象做一些改变有可能会出错。当Ӟq与~译器有养I例如Qvc6、vc7都对此作了扩展,所以,用时对象做左|~译器ƈ没有报错?br>   Q?0Q与static搭配会不会有问题Q?br>        假设有一个类Q?br>        class A
        {
         public:
             ......
             static void f() const { ......}
             ......
         };
         我们发现~译器会报错Q因为在q种情况下static不能够与const共存Q?br>         Z么呢Q因为static没有this指针Q但是const修饰this指针Q所?..
     Q?1Q如何修改常量?
          有时候我们却不得不对cd的数据进行修改,但是我们的接口却被声明了constQ那该怎么处理呢?我对q个问题的看法如下:
           1Q标准用法:mutable
              class A
              {
               public:
                      A(int i=0):test(i)        { }
                      void SetValue(int i)const { test=i; }
               private:
                      mutable int test;   file://q?/font>里处理!
               }Q?br>           2Q强制{换:const_cast
               class A
               {
               public:
                      A(int i=0):test(i)        { }
                      void SetValue(int i)const
                      { const_cast <int>(test)=i; }//q里处理Q?br>               private:
                      int test;  
               }Q?br>            3Q灵zȝ指针Qint*
               class A
              {
               public:
                      A(int i=0):test(i)        { }
                      void SetValue(int i)const
                      { *test=i; }
               private:
                      int* test;   file://q?/font>里处理!
               }Q?br>            4Q未定义的处?br>              class A
              {
               public:
                      A(int i=0):test(i)        { }
                      void SetValue(int i)const
                      { int *p=(int*)&test; *p=i; }//q里处理Q?br>               private:
                      int test;  
               }Q?br>                注意Q这里虽然说可以q样修改Q但l果是未定义的,避免使用Q?br>             5Q内部处理:this指针
              class A
              {
               public:
                      A(int i=0):test(i)        { }
                      void SetValue(int i)const
                      { ((A*)this)->test=i; }//q里处理Q?br>               private:
                      int test;  
               }Q?br>             6Q最另类的处理:I间布局
               class A
               {
                public:
                      A(int i=0):test(i),c('a') {  }
                private:
                      char c;
                      const int test;
                };
                int main()
                {
                    A a(3);
                    A* pa=&a;
                    char* p=(char*)pa;    
                    int*  pi=(int*)(p+4Q;//利用边缘调整
                    *pi=5;                 file://?/font>处改变了test的|
                    return 0;
                 }
        虽然我给Z6中方法,但是我只是想说明如何更改Q但ZW一U用法之外,另外5U用法,我们q不提倡,不要因ؓ我这么写了,你就q么用,否则Q我真是要误人子弟了Q)
     Q?2Q最后我们来讨论一下常量对象的动态创建?br>           既然~译器可以动态初始化帔RQ就自然可以动态创建,例如Q?br>           const int* pi=new const int(10);
           q里要注?点:
           1Qconst对象必须被初始化Q所?10)是不能够的?br>           2Qnewq回的指针必Lconstcd的?br>           那么我们可不可以动态创Z个数l呢Q?br>           {案是否定的Q因为new内置cd的数l,不能被初始化?br>           q里我们忽视了数l是cȝ型的Q同样对于类内部数组初始化我们也做出了这L忽视Q因涉及到数l的问题Q我们以后再讨论?br>



宝杉 2007-10-26 08:31 发表评论
]]>
<?gt;dll详细介绍http://www.shnenglu.com/robinson119/archive/2007/09/04/31539.html宝杉宝杉Tue, 04 Sep 2007 02:46:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/09/04/31539.htmlhttp://www.shnenglu.com/robinson119/comments/31539.htmlhttp://www.shnenglu.com/robinson119/archive/2007/09/04/31539.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/31539.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/31539.html阅读全文

宝杉 2007-09-04 10:46 发表评论
]]>
8-28模板http://www.shnenglu.com/robinson119/archive/2007/08/30/31197.html宝杉宝杉Thu, 30 Aug 2007 02:47:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/30/31197.htmlhttp://www.shnenglu.com/robinson119/comments/31197.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/30/31197.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/31197.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/31197.html模板是重用机制的一U工P可以实现cd参数化,xcd定义为参敎ͼ实现代码可重用性?/span>

 

FQ宏定义也可以实现重用,Z么不使用宏?

QQ宏避开C++cd查机Ӟ两个不同cd参数之间的比较将会导致错误?/span>

 

模板Q模板函敎ͼ模板cd对象之间的关pR?/span>

模板

Q函数模板和cL板)

模板函数

模板c?/span>

对象

头代表实例?/span>

 

模板

Q函数模板和cL板)

模板函数

模板c?/span>

对象

 

例如Q?/span>

C++exams\template_max

模板形参?/span>T实例化的参数?/span>

函数模板是一个不完全的函敎ͼ首先需要将模板形参T实例化ؓ定的类型。这个类型可以是预定义的Q也可以是用戯定义?/span>

 

模板函数的异?/span>

1 先调用顺序遵循什么约定?

Q?/span>1Q寻扄型完全匹配的函数?/span>

Q?/span>2Q寻扑և数模板,实例化后Q生匹配的模板函数?/span>

Q?/span>3Q若Q?/span>1Q(2Q失败,试低一U的对函数重载的Ҏ。例如,通过cd转换?/span>

Q?/span>4Q(1Q(2Q(3Q都为匹配,则是一个错误?/span>

 

2 先了解了q样的约定,很Ҏ理解以下Q?/span>

用非模板函数重蝲函数模板Q只声明非模板类函数的原型,不给出函CQ而函C借用函数模板的函C?/span>

例如Q?/span>

template <class T>

T max( T x, T y)

{

         return( x > y )? x : y;

}

int max( int, int);

//int max 重蝲了函数模板的函数体;

int i;

char c;

maxQ?/span>i, cQ?/span>;

 

 

3 定义一个完整的有函C的非模板函数?/span>

比如Q?/span>max(char, char)Ӟ上面的函数模板不能比较比一个字W更长的字符串了?/span>

所以,像一般的重蝲函数一样定义?/span>

char *max( char *x, char *y )

{

         return ( strcmp(x, y) > 0 ) ? x Q?/span>yQ?/span>

}

char * max重蝲了函数模板,当调用ؓQ?/span>

max ( “abcd”, “efgh” ); 执行此函数?/span>



宝杉 2007-08-30 10:47 发表评论
]]>
08-22http://www.shnenglu.com/robinson119/archive/2007/08/30/31194.html宝杉宝杉Thu, 30 Aug 2007 02:33:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/30/31194.htmlhttp://www.shnenglu.com/robinson119/comments/31194.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/30/31194.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/31194.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/31194.html如果不想让别Z用编译器~写构造拷贝和赋值函敎ͼ可以声明为私有:

     class A

     {

       private:

         A(const A &a);                   // U有的拷贝构造函?span lang=EN-US>

         A & operate =(const A &a);  // U有的赋值函?span lang=EN-US>

     };

 

如果有h试图~写如下E序Q?/span>

     A  b(a); // 调用了私有的拯构造函?span lang=EN-US>

     b = a;        // 调用了私有的赋值函?span lang=EN-US>

~译器将指出错误Q因为外界不可以操作A的私有函数?/span>

但是怎样才能使用构造拷贝和赋值函数呢Q?/span>

虚拟函数使用Q?/span>C++exams\destructor

 

在编写派生类的赋值函数时Q注意不要忘记对基类的数据成员重新赋倹{例如:

C++exams\base_operator



宝杉 2007-08-30 10:33 发表评论
]]>
08-14 Stringc?/title><link>http://www.shnenglu.com/robinson119/archive/2007/08/30/31193.html</link><dc:creator>宝杉</dc:creator><author>宝杉</author><pubDate>Thu, 30 Aug 2007 02:31:00 GMT</pubDate><guid>http://www.shnenglu.com/robinson119/archive/2007/08/30/31193.html</guid><wfw:comment>http://www.shnenglu.com/robinson119/comments/31193.html</wfw:comment><comments>http://www.shnenglu.com/robinson119/archive/2007/08/30/31193.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/robinson119/comments/commentRss/31193.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/robinson119/services/trackbacks/31193.html</trackback:ping><description><![CDATA[     摘要: 定义Q?     class String      {        public:          String(const char *str = NULL);  ...  <a href='http://www.shnenglu.com/robinson119/archive/2007/08/30/31193.html'>阅读全文</a><img src ="http://www.shnenglu.com/robinson119/aggbug/31193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/robinson119/" target="_blank">宝杉</a> 2007-08-30 10:31 <a href="http://www.shnenglu.com/robinson119/archive/2007/08/30/31193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>08-13复习http://www.shnenglu.com/robinson119/archive/2007/08/30/31192.html宝杉宝杉Thu, 30 Aug 2007 02:28:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/30/31192.htmlhttp://www.shnenglu.com/robinson119/comments/31192.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/30/31192.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/31192.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/31192.html 

析构函数

构造函数初始化表:构造函数特D的初始化方?#8220;初始化表辑ּ?#8221;Q简U初始化表)?/p>

初始化表位于函数参数表之后,却在函数?{} 之前。这说明该表里的初始化工作发生在函数体内的Q何代码被执行之前?/p>

规则

u       如果cd在承关p,zcdd其初始化表里调用基类的构造函数?/p>

u       cȝconst帔R只能在初始化表里被初始化Q因为它不能在函C内用赋值的方式来初始化?/p>

u       cȝ数据成员的初始化可以采用初始化表或函C内赋gU方式,q两U方式的效率不完全相同?/p>

效率

1 内部成员Q?/p>

初始化表和函C内赋值都可以Q但效率不完全相同,但后者更为清晰直观?/p>

例子Q?/p>

class F

{

 public:

    F(int x, int y);        // 构造函?/p>

 private:

    int m_x, m_y;

    int m_i, m_j;

}

F::F(int x, int y)

 : m_x(x), m_y(y)          

{

   m_i = 0;

   m_j = 0;

}

F::F(int x, int y)

{

   m_x = x;

   m_y = y;

   m_i = 0;

   m_j = 0;

}

CZ9-2(c) 数据成员在初始化表中被初始化     CZ9-2(d) 数据成员在函C内被初始?/p>

两种方式效率区别不大?/p>

 

2 非内部成员:

只能用初始化表,提高效率?/p>

例子Q?/p>

    class A

{…

    A(void);                // 无参数构造函?/p>

    A(const A &other);      // 拯构造函?/p>

    A & operate =( const A &other); // 赋值函?/p>

}Q?/p>

 

    class B

    {

     public:

        B(const A &a); // B的构造函?/p>

     private: 

        A m_a;         // 成员对象

};

比较与分析:

B::B(const A &a)

 : m_a(a)          

{

   …

}

B::B(const A &a)

{

m_a = a;

}

1 BcL造函数的初始化里Q调用了Acȝ拯构造函数?/p>

2 BcL造初始化里,隐藏了以下几个步骤:

先创Za对象Q调用了Acȝ无参数构造函敎ͼ

把a赋值给m_aQ调用了Acȝ赋值函敎ͼ

 

深入探讨Q?/p>

构造和析构的次序?

构造从最深处的基cd始的Q先一层层调用基类的构造函敎ͼ然后调用成员对象的构造函数?/p>

而析构函C格按照构造函数相反的ơ序执行Q该ơ序唯一Q以便让~译器自动执行析构函数?/p>

特别之处是,成员对象初始化次序不受构造函数初始化表次序媄响,由在cM声明的次序决定。而类声明是唯一的,构造函数却可能有多个,所以有多个不同ơ序函数初始化表。如果按照构造函数的ơ序构造,那么解析函数不能得到唯一的逆序?/p>

宝杉 2007-08-30 10:28 发表评论
]]>
example1http://www.shnenglu.com/robinson119/archive/2007/08/20/30436.html宝杉宝杉Mon, 20 Aug 2007 09:01:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/20/30436.htmlhttp://www.shnenglu.com/robinson119/comments/30436.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/20/30436.html#Feedback2http://www.shnenglu.com/robinson119/comments/commentRss/30436.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/30436.html#include <iostream>
using namespace std;
#include <stdio.h>

#define OTL_ORA7 // Compile OTL 3.1/OCI7
#include <otlv4.h> // include the OTL 4 header file

otl_connect db; // connect object

void insert()
// insert rows into table
{
 otl_stream o(50, // buffer size
              "insert into test_tab values(:f1<float>,:f2<char[31]>)",
                 // SQL statement
              db // connect object
             );
 char tmp[32];

 for(int i=1;i<=100;++i){
  sprintf(tmp,"Name%d",i);
  o<<(float)i<<tmp;
 }
}

void select()
{
 otl_stream i(50, // buffer size
              "select * from test_tab where f1>=:f<int> and f1<=:f*2",
                 // SELECT statement
              db // connect object
             );
   // create select stream
 
 float f1;
 char f2[31];

 i<<8; // assigning :f = 8
   // SELECT automatically executes when all input variables are
   // assigned. First portion of output rows is fetched to the buffer

 while(!i.eof()){ // while not end-of-data
  i>>f1>>f2;
  cout<<"f1="<<f1<<", f2="<<f2<<endl;
 }

 i<<4; // assigning :f = 4
   // SELECT automatically executes when all input variables are
   // assigned. First portion of output rows is fetched to the buffer

 while(!i.eof()){ // while not end-of-data
  i>>f1>>f2;
  cout<<"f1="<<f1<<", f2="<<f2<<endl;
 }

}

int main()
{
 otl_connect::otl_initialize(); // initialize OCI environment
 try{

  db.rlogon("scott/tiger"); // connect to Oracle

  otl_cursor::direct_exec
   (
    db,
    "drop table test_tab",
    otl_exception::disabled // disable OTL exceptions
   ); // drop table

  otl_cursor::direct_exec
   (
    db,
    "create table test_tab(f1 number, f2 varchar2(30))"
    );  // create table

  insert(); // insert records into table
  select(); // select records from table

 }

 catch(otl_exception& p){ // intercept OTL exceptions
  cerr<<p.msg<<endl; // print out error message
  cerr<<p.stm_text<<endl; // print out SQL that caused the error
  cerr<<p.var_info<<endl; // print out the variable that caused the error
 }

 db.logoff(); // disconnect from Oracle

 return 0;

}



宝杉 2007-08-20 17:01 发表评论
]]>
OTL 4.0, OTL concepthttp://www.shnenglu.com/robinson119/archive/2007/08/20/30435.html宝杉宝杉Mon, 20 Aug 2007 08:58:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/20/30435.htmlhttp://www.shnenglu.com/robinson119/comments/30435.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/20/30435.html#Feedback4http://www.shnenglu.com/robinson119/comments/commentRss/30435.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/30435.htmlOTL stream concept

Any SQL statement, PL/SQL block or a stored procedure call is characterized by its input / output [variables].

Example 1. A SELECT statement has scalar input variables that are used in the WHERE clause of the statement. The SELECT statement also defines output columns. Potentially, the output columns are vector parameters since the SELECT statement may return multiple rows.

Example 2. An INSERT statement writes data into a table, i.e. it has input parameters. Same is true for UPDATE statemements.

Example 3. A DELETE statement deletes rows from a table. Deletion criteria needs to be entered, thus the DELETE statement has input.

Example 4. A stored procedure may have input and/or output parameters. Usually, stored procedure parameters are scalars. There is a special case, though: stored procedure returning a referenced cursor (Oracle) or a result set (MS SQL Server or Sybase).

Example 5. An arbitrary PL/SQL block may have input or/and output parameters that may be either scalars or vectors.

Industrial strength database servers have bulk (or array) operations:

  • bulk INSERT
  • bulk UPDATE
  • bulk DELETE
  • bulk SELECT

Therefore, parameters in INSERT/UPDATE/DELETE statement may be vectors if the statement is performed in bulk.

The picture is clear: any interaction with SQL or its procedural extension can be treated as a black box with input and/or output. It does not matter what the black box does inside (according to the definition of a black box). What matters is the input wires that send signals into the box and the output wires that receive signals from the box:

Some of the wires may be both input and output.

Why not combine the concept of data streams and SQL? Instead of multiplying constructs and making database API's too convoluted, why not unify and simplify them? The OTL gives an answer to those questions and the answer is the otl_stream class.

Since a SQL statement may be done in bulk, the otl_stream is a buffered stream. Conceptually, the otl_stream has two separate buffers: input and output. The input buffer is comprised of all input variables put together. Respectively, the output buffer is comprised of all output variables put together.

C++ streams are usually manipulated via operator >> and operator <<. The stream reference is on the left of the operator symbol:

   s>>variable;
s<<variable;

The double arrow shows the direction in which data goes:

  • >> -- from the stream into the data container (variable)
  • << -- from the data container (variable) into the stream

OTL streams are similar to buffered C++ streams . A SQL statement or stored procedure call is opened as an ordinary buffered stream. The logic of the OTL stream operations remains the same as the C++ stream operations with the only exception -- the OTL stream has separate input and output buffers which may overlap.

The OTL stream has a flush function for flushing its input buffer when the buffer gets full and a collection of >> and << operators for reading and writing objects of different data types. The most important advantage of the OTL streams is their unified interface to SQL statements and stored procedure call of any kind. This means that the application developer needs to remember just a few syntactical constructs and function names which he already got familiar with when he started working with C++ streams.

Inside the OTL stream there is a small parser for parsing declarations of bind variables and their data types. There is no need to declare C/C++ host variables and bind them with placeholders by special bind function calls. All necessary buffers are created dynamically inside the stream. The stream just needs to be opened for reading and writing values.

The OTL stream interface requires use of the OTL exceptions. This means that potentially any OTL stream operation can throw an exception of the otl_exception type. In order to intercept the exception and prevent the program from aborting, wrap up the OTL stream code with the corresponding try & catch block.

The functioning of the otl_stream is pretty much automatic: when all of the input variables of the stream are defined (in other words, the input buffer is filled out), it triggers the block box inside the stream to execute. The output buffer gets filled out in the process of the execution of the black box. After the execution is finished, the output values can be read from the stream. If it is a SELECT statement and it returns more rows than the output buffer can hold, after the whole output buffer is read, then the stream automatically fetches the next bacth of rows into the output buffer.



宝杉 2007-08-20 16:58 发表评论
]]>
OTL 4.0, Introductionhttp://www.shnenglu.com/robinson119/archive/2007/08/20/30434.html宝杉宝杉Mon, 20 Aug 2007 08:55:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/20/30434.htmlhttp://www.shnenglu.com/robinson119/comments/30434.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/20/30434.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/30434.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/30434.htmlIntroduction This document describes the Oracle, Odbc and DB2-CLI Template Library, Version 4.0 (OTL 4.0). OTL 4.0 is a C++ library based on templates. It integrates all of the previous releases into one library.

OTL 4.0 was designed as a combination of a C++ template framework and OTL-adapters. The framework is a generic implementation of the concept of OTL streams. The OTL-adapters are thin wrappers around the database APIs and are used as class type parameters to be substituted into the template framework.

OTL 4.0 covers the functionality of a whole database API with just a handful of concrete classes: otl_stream, otl_connect, otl_exception, otl_long_string, and several template PL/SQL (Oracle) table container classes, generated from the template framework and the OTL-adapters.

The OTL code gets expanded into direct database API function calls, so it provides ultimate performance, reliability and thread safety in multi-processor environments as well as traditional batch programs. OTL 4.0, being a template library, is highly portable since it is self-sufficient and compact enough.

OTL 4.0 is ANSI C++ compliant (ANSI C++ typecasts, clean templatized code, etc.), tightly integrated with the Standard Template Library (STL) via so-called STL-compliant stream iterators, and natively supports the STL std::string's in otl_stream's.

The current version of the OTL supports Oracle 7 (natively via OCI7), Oracle 8 (natively via OCI8), Oracle 8i (natively via OCI8i), Oracle 9i (natively via OCI9i), Oracle 10g (natively via OCI10g), DB2 (natively via DB2 CLI), ODBC 3.x as well as ODBC 2.5 compliant data sources in MS Windows and Unix (e.g. Oracle, MS SQL Server, Sybase, Informix, MySQL, DB2, Interbase / Firebird, PostgreSQL, SQLite, SAP/DB, TimesTen, MS ACCESS, etc.). The list of supported database backends is constantly growing.



宝杉 2007-08-20 16:55 发表评论
]]>
08-10 内联函数http://www.shnenglu.com/robinson119/archive/2007/08/13/29886.html宝杉宝杉Mon, 13 Aug 2007 02:24:00 GMThttp://www.shnenglu.com/robinson119/archive/2007/08/13/29886.htmlhttp://www.shnenglu.com/robinson119/comments/29886.htmlhttp://www.shnenglu.com/robinson119/archive/2007/08/13/29886.html#Feedback0http://www.shnenglu.com/robinson119/comments/commentRss/29886.htmlhttp://www.shnenglu.com/robinson119/services/trackbacks/29886.html内联函数Q既增加安全性,又可以调用类的数据成员?/span>

?/span>C++中,用内联取代所有宏Q但?/span>Debug版本中,assert是例外?/span>

assert不生Q何副作用Q调用函C引v内存、代码的变动Q所?/span>assert是宏?/span>

内联格式Q?/span>

     void Foo(int x, int y);    

     inline void Foo(int x, int y)    // inline与函数定义体攑֜一?span lang=EN-US>

     {

        

     }

用于实现的关键字Q而非用于声明的关键字?/span>

在类中的规范格式Q?/span>

class A

     {

public:

         void Foo(int x, int y)Q?span lang=EN-US>

     }

     // 定义文g

     inline void A::Foo(int x, int y)

{

}

什么情况不适合使用内联Q?/span>

1 内联函数代码较长Q导致内存消耗较高?/span>

2 内联函数包括循环Q执行内联函C码比调用函数的开销大?/span>

FQؓ什么构造和解析函数不用内联?

QQ因为析构函数可?#8220;隐藏”一些行为,例如执行基类或成员对象的析构q程?/span>

有时候编译器会自动取消一些不值得的内联,所以在声明时不?/span>inline是合理的?/span>



宝杉 2007-08-13 10:24 发表评论
]]>
þĻƵ| Ůþþùһ| ޾ƷþþþĻһڣ| þ99Ʒþþþþ| ҹҹþ| 91Ʒþþþþ| 99þþƷһ| þþƷר| þùƷ99Ʒ| þþþþ| ƷþþþӰԺ۲| þۺϺݺɫۺ| 99þۺϹƷ| ƷžžþƵ | Ʒþþþ龫Ʒ| 2021ٸþþþþþþþ| þùѹۿƷ| Ʒþۺ123| þ99Ʒ鶹| ޾Ʒҹvaþ| ˳վþ99ȹ | ƷþùƷ99| һֻƴƬ99þ| þùֱ| 2021þþƷѹۿ| ٸ߳ҽоþþ| 91Ըߺþþþ| 2021þþƷѹۿ| þ96Ʒþþ| һþƵ| þ99ۺϾƷŮͬ| þù| þþƷav鶹С˵| Ʒ91þþþþþa| AVþþƷ| Ʒþþþþþþþ| 99þùƷһ| 99þþƷۺһ| ޹ŷۺϾþ| 99þþƷѹƬ| ƷþþþþĻһ |