posts - 29, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          摘自:《高質量的 C++編程》 

           

          8.2.1重載與覆蓋
              成員函數被重載的特征:
          1)相同的范圍(在同一個類中);
          2)函數名字相同;
          3)參數不同;
          4)virtual關鍵字可有可無。
              覆蓋是指派生類函數覆蓋基類函數,特征是:
          1)不同的范圍(分別位于派生類與基類);
          2)函數名字相同;
          3)參數相同;
          4)基類函數必須有virtual關鍵字。
           
           
          “隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
          1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
          (2)如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)。
           
           
          如下示例程序中:
          1)函數Derived::f(float)覆蓋了Base::f(float)。
          2)函數Derived::g(int)隱藏了Base::g(float),而不是重載。
          3)函數Derived::h(float)隱藏了Base::h(float),而不是覆蓋。
           
          #include <iostream.h>
              class Base
          {
          public:
              virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
          void g(float x){ cout << "Base::g(float) " << x << endl; }
                      void h(float x){ cout << "Base::h(float) " << x << endl; }
          };
              class Derived : public Base
          {
          public:
              virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
          void g(int x){ cout << "Derived::g(int) " << x << endl; }
                      void h(float x){ cout << "Derived::h(float) " << x << endl; }
          };

            
          void main(void)
          {
          Derived d;
          Base *pb = &d;
          Derived *pd = &d;
          // Good : behavior depends solely on type of the object
          pb->f(3.14f); // Derived::f(float) 3.14
          pd->f(3.14f); // Derived::f(float) 3.14
           
          // Bad : behavior depends on type of the pointer
          pb->g(3.14f); // Base::g(float) 3.14
          pd->g(3.14f); // Derived::g(int) 3        (surprise!)
           
          // Bad : behavior depends on type of the pointer
          //行為(即方法的調用)依賴于指針的類型
          pb->h(3.14f); // Base::h(float) 3.14      (surprise!)
          pd->h(3.14f); // Derived::h(float) 3.14
          }

           

          posted @ 2007-05-28 15:45 change| 編輯 收藏

          引用就是別名。
          引用的一些規則如下:
          1)引用被創建的同時必須被初始化(指針則可以在任何時候被初始化)。
          2)不能有NULL引用,引用必須與合法的存儲單元關聯(指針則可以是NULL)。

          (3)一旦引用被初始化,就不能改變引用的關系(指針則可以隨時改變所指的對象)。

          “引用傳遞”的性質象“指針傳遞”(能夠改變原來的參數值),而書寫方式象“值傳遞”。

          posted @ 2007-05-28 15:45 change| 編輯 收藏

            最近找工作,幾乎所有的公司有要考C/C++ ,沒有辦法,呵呵~~~~只有慢慢的開始 拾起 C++ 來,好久沒有弄過C++ 了,基本語法都忘得差不多了,呵呵~~~今天看了《高質量的 C++編程》,現摘下一些話,已備忘記查找。

            

          C++內存分配方式
          內存分配方式有三種:
          (1)      從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。
          (2)      在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
          (3)      從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。
          EG:
                     用函數返回值來傳遞動態內存
           
          char *GetMemory3(int num)
          {
              char *p = (char *)malloc(sizeof(char) * num);
              return p;
          }
          void Test3(void)
          {
              char *str = NULL;
              str = GetMemory3(100); 
              strcpy(str, "hello");
              cout<< str << endl;
              free(str); 
          }

           但是下面這種事有問題的:

              
          char *GetString(void)
          {
              char p[] = "hello world";
              return p;   // 編譯器將提出警告
          }
          void Test4(void)
          {
          char *str = NULL;
          str = GetString(); // str 的內容是垃圾
          cout<< str << endl;
          }

           

          這里強調不要用return語句返回指向“棧內存”的指針,因為該內存在函數結束時自動消亡,如上面的示例。  用調試器逐步跟蹤Test4,發現執行str = GetString語句后str不再是NULL指針,但是str的內容不是“hello world”而是垃圾。

           

          如果把示例7-4-4改寫成示例7-4-5,會怎么樣?
           

          char *GetString2(void)
          {
              char *p = "hello world";
              return p;
          }
          void Test5(void)
          {
              char *str = NULL;
              str = GetString2();
              cout<< str << endl;
          }

          示例7-4-5 return語句返回常量字符串
           

          函數Test5運行雖然不會出錯,但是函數GetString2的設計概念卻是錯誤的。因為GetString2內的“hello world”是常量字符串,位于靜態存儲區,它在程序生命期內恒定不變。無論什么時候調用GetString2,它返回的始終是同一個“只讀”的內存塊

           

          posted @ 2007-05-28 15:44 change| 編輯 收藏

          在jxta里面,所有的資源都是通過廣告來發布的,這里的服務業不例外,在這里的服務  發布里面有兩個很總要的概念,

          • ModuleClassAdvertisement— defines the service class; its main purpose is to formally document the
          existence of a module class. It is uniquely identified by a ModuleClassID.
          • ModuleSpecAdvertisement — defines a service specification; uniquely identified by a ModuleSpecID.
          Its main purpose is to provide references to the documentation needed in order to create conforming
          implementations of that specification. A secondary use is to make running instances usable remotely,
          by publishing any or all of the following:
          • PipeAdvertisement
          • ModuleSpecID of a proxy module
          • ModuleSpecID of an authenticator module
          • ModuleImplAdvertisement — defines an implementation of a given service specification. 

          這里的 ModuleClassAdvertisement  僅僅用來告知服務的存在,對等點若是需要訪問該服務的話,還需要發現與之關聯的 ModuleSpecAdvertisement  廣告信息。

          而這里的 ModuleSpecAdvertisement  則包含了 對等點節點 要訪問該服務所需要的所有相關信息,比如:管道廣告信息,通過它才能夠連接上所需要的服務。

          服務端的代碼示例大抵如下:

          創建發布 ModuleClassAdvertisement  :

          ModuleClassAdvertisement mcadv = (ModuleClassAdvertisement)AdvertisementFactory.newAdvertisement(ModuleClassAdvertisement.getAdvertisementType());
             mcadv.setName("JXTAMOD:JXTA-EX1");
             mcadv.setDescription("Tutorial example to use JXTA module advertisement Framework");
             ModuleClassID mcID = IDFactory.newModuleClassID();
             mcadv.setModuleClassID(mcID);//通過mcID來建立ModuleClassAdvertisement 與ModuleSpecAdvertisement 的聯系

          discovery.publish(mcadv);
           discovery.remotePublish(mcadv);

          創建發布 ModuleSpecAdvertisement :

          ModuleSpecAdvertisement mdadv = (ModuleSpecAdvertisement)AdvertisementFactory.newAdvertisement(ModuleSpecAdvertisement.getAdvertisementType());

          mdadv.setName("JXTASPEC:JXTA-EX1");
             mdadv.setVersion("Version 1.0");
             mdadv.setCreator("sun.com");
             mdadv.setModuleSpecID(IDFactory.newModuleSpecID(mcID));
             mdadv.setSpecURI("http://www.jxta.org/Ex1");

          PipeAdvertisement pipeadv = null;
             try {
              FileInputStream is = new FileInputStream("pipeserver.adv");
              pipeadv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8, is);
              is.close();
             } catch (Exception e) {
              System.out.println("failed to read/parse pipe advertisement");
             }

          mdadv.setPipeAdvertisement(pipeadv);

          discovery.publish(mdadv);
           discovery.remotePublish(mdadv);
            myPipe = pipes.createInputPipe(pipeadv);

          在客戶端,通過不斷的查找廣告(分本地查找和遠端查找)來 獲取 所需要服務的廣告信息,通過它就可以獲取 管道信息 來創建管道以達到通訊的目的。客戶端代碼示例大抵如下:

          Enumeration en = null;
            while (true) {
             try {
              /* let's look first in our local cache to see if we have it! We try to discover an adverisement which as the (Name, JXTA-EX1) tag value
              en = discovery.getLocalAdvertisements(DiscoveryService.ADV,"Name","JXTASPEC:JXTA-EX1");
              //  Ok we got something in our local cache does not
              //  need to go further!
              if ((en != null) && en.hasMoreElements()) {
               break;
              }
              //  nothing in the local cache?, let's remotely query
              //  for the service advertisement.
              discovery.getRemoteAdvertisements(null,DiscoveryService.ADV,"Name","JXTASPEC:JXTA-EX1",1, null);
              //  The discovery is asynchronous as we do not know
              //  how long is going to take
              try { // sleep as much as we want. Yes we
               //  should implement asynchronous listener pipe...
               Thread.sleep(2000);
              } catch (Exception e) {}
             } catch (IOException e) {
              //  found nothing! move on
             }
             System.out.print(".");
            }
            System.out.println("we found the service advertisement");
            //  Ok get the service advertisement as a Spec Advertisement
            ModuleSpecAdvertisement mdsadv = (ModuleSpecAdvertisement)en.nextElement();
            try {
             //  let's print the advertisement as a plain text document
             StructuredTextDocument doc = (StructuredTextDocument)mdsadv.getDocument(MimeMediaType.TEXT_DEFAULTENCODING);
             StringWriter out = new StringWriter();
             doc.sendToWriter(out);
             System.out.println(out.toString());
             out.close();
             //  we can find the pipe to connect to the service
             //  in the advertisement.
             PipeAdvertisement pipeadv = mdsadv.getPipeAdvertisement();
             //  Ok we have our pipe advertiseemnt to talk to the service
             //  create the output pipe endpoint to connect  to the server
              myPipe = pipes.createOutputPipe(pipeadv, 10000);
             }

             //  send the message to the service pipe
             myPipe.send (msg);

          posted @ 2007-05-28 15:41 change| 編輯 收藏

          JXTA 雙向通訊 可以通過 JxtaServerSocket /JxtaSocket和 JxtaServerPipe/JxtaBiDiPipe 來實現 其實現的過程非常的類是我們做FTP的時候所采用的ServerSocket/Socket機制,也就是服務斷監聽客戶端連接的原理。以JxtaServerPipe為例,在服務端:

          serverPipe = new JxtaServerPipe(eg.netPeerGroup,eg.pipeAdv);

          serverPipe.setPipeTimeout(0);然后就是服務端的循環監聽客戶端的連接

          while (true) {
             try {
              JxtaBiDiPipe bipipe = serverPipe.accept();
              if (bipipe != null ) {
               System.out.println("JxtaBidiPipe accepted,sending 100 messages to the other end");
               //Send a 100 messages
               sendTestMessages(bipipe);
              }
             } catch (Exception e) {
               }
            }

          在客戶端則是通過JxtaBiDiPipe 來進行連接服務斷的操作:pipe = new JxtaBiDiPipe();

          pipe.connect(eg.netPeerGroup,null,eg.pipeAdv,
              180000,
              // register as a message listener
              eg);當有消息來得時候就會觸發 pipeMsgEvent(PipeMsgEvent event)事件

          posted @ 2007-05-28 15:41 change| 編輯 收藏

          最近在JXTA的官方網站上面下載了一份JxtaProgGuide看了看,練習了一下上面的示例程序~~~~大抵上感覺的編程的模式就是:

          //Method to start the JXTA platform.

          NetPeerGroupFactory factory  = new NetPeerGroupFactory();//這是默認的創建的一個組。
                  netPeerGroup = factory.getInterface(); 

          然后就是獲取相應的服務如發現服務(用于發現和發布廣告,那么什么是廣告呢?

          Advertisements 就是:
          All JXTA network resources— such as peers, peer groups, pipes, and services —are represented by an
          advertisement. Advertisements are language-neutral meta-data structures represented as XML documents. The
          JXTAprotocols use advertisements to describe and publish the existence of a peer resources. Peers discover
          resources by searching for their corresponding advertisements, and may cache any discovered advertisements
          locally.),管道服務(用于創建IN/OUT管道來接發消息,這里創建OutPipe管道會觸發outputPipeEvent(OutputPipeEvent event) 事件,而當 Inpipe 管道有消息到來的時候會觸發pipeMsgEvent(PipeMsgEvent event)事件 ,而這里In/Out 管道間的聯系則就是廣告的用處了,它通過PipeID標示出所用的管道來建立他們之間的聯系而不至于混亂。對等點間的通訊就要依賴于它了)

          discovery = netPeerGroup.getDiscoveryService();
           rdv = netPeerGroup.getRendezVousService();

          然后是通過所獲取的服務來注冊監聽器在通過發現事件來獲取一個廣告,或者是直接通過服務來獲取一個廣告,總之目的就是要獲取一個所要找的廣告 。如監聽:

          discovery.addDiscoveryListener(this);此時需要implements DiscoveryListener接口,

          實現里面的 discoveryEvent(DiscoveryEvent ev) 方法,然后通過 DiscoveryEvent  獲取廣告

          DiscoveryResponseMsg res = ev.getResponse();
            // Get the responding peer's advertisement
            PeerAdvertisement peerAdv = res.getPeerAdvertisement();

          或者是直接通過服務來獲取一個廣告

          discovery.getRemoteAdvertisements(null, DiscoveryService.GROUP, null, null, 5);

          在要不就是i通過一個發現服務來發布一個廣告,這里的發布廣告分本地發布和遠程發布

          discoveryService.publish(Adv,PeerGroup.DEFAULT_LIFETIME,PeerGroup.DEFAULT_EXPIRATION);
           discoveryService.remotePublish(Adv,PeerGroup.DEFAULT_EXPIRATION);

           那么一個對等點如何才能夠加入一個Group呢

          StructuredDocument creds = null;

          // Generate the credentials for the Peer Group
             AuthenticationCredential authCred = new AuthenticationCredential( grp, null, creds );
             // Get the MembershipService from the peer group
             MembershipService membership = grp.getMembershipService();
             // Get the Authenticator from the Authentication creds
             Authenticator auth = membership.apply( authCred );
             // Check if everything is okay to join the group
             if (auth.isReadyForJoin()){
              Credential myCred = membership.join(auth);
              System.out.println("Successfully joined group " + grp.getPeerGroupName());
              // display the credential as a plain text document.
              System.out.println("\nCredential: ");
              StructuredTextDocument doc = (StructuredTextDocument)myCred.getDocument(new MimeMediaType("text/plain"));
              StringWriter out = new StringWriter();
              doc.sendToWriter(out);
              System.out.println(out.toString());
              out.close();
             }

           

          posted @ 2007-05-28 15:40 change| 編輯 收藏

          最近也算是閑來無事, 于是乎開始玩玩 J2ME 無線編程,找了一本書翻翻,然后下載了一個 ME插件和諾基亞的模擬器 做了幾個小例子,發覺其實也沒有什么,感覺基本上可以說是windows 窗口編成的一個縮版(新手愚見,高手見效了)。就是所謂的添加一個form(類是面板),在給他添加幾個TextField(類是文本框),添加相應的響應事件,然后就是在不同的現實面板間切換,做一些業務上的事情,至于手機上的存儲嘛,基本上是依賴于 DataStore 這個類的,用它獲取recordID在獲取記錄等等,也就是通常的數據庫操作(增刪改查)都依賴于它。至于手機的聯網通訊則是依賴于Connector這個對象了,通過它 既可以創建一個Socket連接,也可以創建一個HTTP連接,只是連接的URL 字符串不同罷了。如:

          conn =  (HttpConnection)Connector.open(URL.toString());

          想想它的難點的話應該是如何的精簡代碼,高效的利用存儲空間,和網絡通訊的安全吧。因為這畢竟是一個手持設備的局限性問題。這方面就確實沒有什么經驗了,希望有高手的經驗共享。呵呵~~~我只是感覺她的編程模型還是蠻好理解的。沒有什么神秘可言。我翻的那本書比較的老了,也許現在的MIDP2.0 已經有了很大的改觀也說不來噢,個人沒有怎么了解。不過在J2ME的開發包里面有好多的Demo,但是現在是沒有什么時間去研究它了,呵呵~~~以后再說吧,歡迎大家批評指正。

          posted @ 2007-05-28 15:40 change| 編輯 收藏

          以前的同步操作 基本上都是用到 synchronised 關鍵字,類似代碼如下:

          synchronised(obj){

          //dosomething...

          }來做到同步,

          在 JDK5.0  里面有這么一個對象,ReentrantLock,發覺她的加鎖編程的方式非常的適合日常的加鎖習慣,

          EG:

          package com.thread.synchronise;

          import java.util.concurrent.locks.ReentrantLock;

          public class SynchroTest extends Thread{
           private int count = 0;
           private final ReentrantLock lock = new ReentrantLock();
           
           public void run()
           {

          //這里加了幾次鎖,在后面就的要相應的解鎖 幾次
               
          lock.lock();  // block until condition holds
                try {      
                 count++;
                 System.out.println(" count = "+count);
                 try {
              Thread.sleep(3000);
             } catch (InterruptedException e) {
              e.printStackTrace();
             }
                 System.out.println(" count = "+count);
                } finally {
                
          lock.unlock();
                }
           }
           /**
            * @param args
            */
           public static void main(String[] args) {
            // TODO Auto-generated method stub
            SynchroTest st1 = new SynchroTest();
          //  SynchroTest st2 = new SynchroTest();
          //  SynchroTest st3 = new SynchroTest();
            

          //這里不能夠調用   new Thread(st1).run();方法,否則就不是多線程的了
            new Thread(st1).start();
            new Thread(st1).start();
            new Thread(st1).start();
           }

          }

          如果該線程等待某暫時獲取不到的資源,那么我們可以用Condition Object來避免死鎖情況。
          sufficientFunds = lock .newCondition();
          如果條件不滿足:
          sufficientFunds.await();
          這時線程就會釋放鎖并進入blocked狀態,其他線程就有機會執行操作。當其他線程執行完后,就可通知等待的線程繼續執行它的操作了:
          sufficientFunds.signalAll();


          posted @ 2007-05-28 15:39 change| 編輯 收藏

          //解決二次提交問題(提交前)

                    preSubmitValid(servletRequest,servletResponse);
                    
          //解決二次提交問題(提交)
              if(!submitValid(servletRequest,servletResponse))
               try
                        {
                         servletResponse.sendRedirect("public/repeatdeal.jsp");
                         return null;
                        }
                        catch (Exception error)
                        {
                         servletRequest.setAttribute("errorMSG", "重復提交造成頁面跳轉出錯:" + error.getMessage());
                        }   
                       
          /**
                   * 解決二次提交問題(提交前)

                   * @param request
                   * @param response
                   */
                  public void preSubmitValid(HttpServletRequest servletRequest,HttpServletResponse response)
                  {
                   counter = -1;
                      servletRequest.getSession().setAttribute("submissioncount",
                              new Integer(counter));
                      /**
                       * 重要:

                       * 通過調用 saveToken(request)方法,動態生成一個token,并且存放到session中,
                       * 以便在以后可以在動態生成的頁面中加入隱藏字段 <input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="動態值">
                       * 只要調用了該方法,此后包含<html:form...>標簽的頁面中都會動態生成上面所說的隱藏字段。

                       */
                      this.saveToken(servletRequest);         
                  }
                  /**
                   * 提交驗證,檢驗是否是重復提交,如果重復提交跳轉到統一處理頁面
                   * @param servletRequest
                   * @param servletResponse
                   * @return
                   */
                  public boolean submitValid(HttpServletRequest servletRequest,HttpServletResponse servletResponse)
                  {
                   counter += 1;
                   servletRequest.getSession().setAttribute("submissioncount",new Integer(counter));
                      if (!this.isTokenValid(servletRequest))
                       return false;

                      /**
                       * 在認可了用戶的合法提交后,一定要調用resetToken(request)重置token,這樣session中就沒有相應的token啦

                       * 這樣才能夠保證用戶再次提交相應數據時,能夠檢測出來。

                       */
                      this.resetToken(servletRequest);
                      return true;         
                  }                      

          posted @ 2007-05-28 15:38 change| 編輯 收藏

          以前用得的是hibernate3.0.5的版本~~~~而且關于queryfactory 的配置如下:

          <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>

          因為數據量超出了10萬條~~~~結果出現了 heap 溢出問題,想想了,也確實該溢出了,呵呵~~~

          這種查詢方式,是將所有的查詢出來的結果以對象的形式進行緩存,如此巨大的數據,不把她給稱爆炸才怪呢:)

          查查hibernate 的文檔,有關于大數據量的處理~~~,流程大抵如下:

          Transaction tx = session.beginTransaction();

                  String hqlDelete = "delete VbufferGis ";
                  int deletedEntities = session.createQuery( hqlDelete ).executeUpdate();
                  tx.commit();
                  session.close();

          測試運行出現如下異常:query must begin with SELECT or FROM ,文檔是清清楚楚是這樣寫的嘛,怎么會出現這樣的問題呢,是不是和我剛開始的時候一樣覺得挺納悶的,呵呵~~~原來是配置的問題,將上面的配置改為:

          <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>

          本以為這下是萬事大吉了,呵呵~~~~問題有出來了,define class not foundexception :antlr.antlrexception

          在網上授了一把,原來hibernate用她來解析 hql ,而我用myEclipse的時候,有沒有導入那個包,自然有問題了,

          于是將那個包導入,測試刪除運行,一切ok!這下是真的萬事大吉了嗎?還沒有,這也難怪我的多磨難了,呵呵

          原來在進行待漢字的參數查詢的時候出現了亂碼現象,感覺挺奇怪的,百思不得其解,幸好有網絡這個好東西,google了一下,^_^ 原來值需要換一個版本就ok了,呵呵~~~于是在取sourceforge上面取下了 hibernate-3.1rc2.zip,這下子就ok了!一切運行正常?。。‰m然問題是解決了,原理缺不甚明白,有待學習。。。。

          posted @ 2007-05-28 15:37 change| 編輯 收藏

          僅列出標題
          共3頁: 上一頁 1 2 3 下一頁 
          主站蜘蛛池模板: 亳州市| 长岭县| 滨海县| 梓潼县| 彩票| 丘北县| 桑植县| 宾川县| 莱阳市| 鄂尔多斯市| 崇仁县| 中西区| 西丰县| 水富县| 花莲县| 九台市| 余姚市| 西畴县| 潞西市| 扎囊县| 湛江市| 子长县| 六枝特区| 阿图什市| 河间市| 藁城市| 山西省| 电白县| 敖汉旗| 天全县| 宿迁市| 仁寿县| 双城市| 石泉县| 罗源县| 天等县| 文化| 芜湖市| 砚山县| 日土县| 南皮县|