测试时用的代码
var string:String = new String(); string = "●本节教学的重点是有理数的概念.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点."; putWord(getHeight(string)+14,string); function getHeight(string:String):Number { var MenuTxt_tmp:TextField = new TextField(); var MenuTxt_TextFormat:TextFormat = new TextFormat(); MenuTxt_tmp.name = "toom"; MenuTxt_tmp.width = 160; MenuTxt_tmp.text = string; MenuTxt_tmp.multiline = true; MenuTxt_tmp.wordWrap = true;//自动换行 MenuTxt_TextFormat.leading = 7; MenuTxt_TextFormat.font = "宋体"; MenuTxt_TextFormat.size = 14; MenuTxt_tmp.setTextFormat(MenuTxt_TextFormat); return MenuTxt_tmp.textHeight; } function putWord(wordHeight:Number,string:String):void { var MenuTxt_tmp:TextField = new TextField(); var MenuTxt_TextFormat:TextFormat = new TextFormat(); MenuTxt_tmp.name = "tom"; MenuTxt_tmp.x = 100; MenuTxt_tmp.y = 100; MenuTxt_tmp.width = 160; MenuTxt_tmp.height = wordHeight; MenuTxt_tmp.text = string; MenuTxt_tmp.multiline = true; MenuTxt_tmp.wordWrap = true; MenuTxt_TextFormat.leading = 7; MenuTxt_TextFormat.font = "宋体"; MenuTxt_TextFormat.size = 14; MenuTxt_tmp.setTextFormat(MenuTxt_TextFormat); addChild(MenuTxt_tmp); }
实际项目中用的代码。注意把字体的高度加上来
var string:String = new String(); string = "●本节教学的重点是有理数的概念.\n●建立正数、负数的概念对学生来说是数学抽象思维的一次重大飞跃,是本节教学的难点."; var MenuTxt_tmp:TextField = new TextField(); var MenuTxt_TextFormat:TextFormat = new TextFormat(); MenuTxt_tmp.name = "tom"; MenuTxt_tmp.x = 100; MenuTxt_tmp.y = 100; MenuTxt_tmp.width = 160; MenuTxt_tmp.text = string; MenuTxt_tmp.multiline = true; MenuTxt_tmp.wordWrap = true; MenuTxt_TextFormat.leading = 7; MenuTxt_TextFormat.font = "宋体"; MenuTxt_TextFormat.size = 14; MenuTxt_tmp.setTextFormat(MenuTxt_TextFormat); MenuTxt_tmp.height = MenuTxt_tmp.textHeight+14;//注意把字体的size加上来 addChild(MenuTxt_tmp);
/*by garcon1986*/
Based on my last post about
how to create, host, test and consume WCF Service, here we will discover how to create RESTful WCF Service.
“Representational State Transfer (REST) is a style of software architecture for distributed systems such as the World Wide Web. REST has emerged as a predominant Web service design model.” from wiki
“Those principles of REST service are:
User agents interact with resources, and resources are anything that can be named and represented. Each resource can be addressed via a unique Uniform Resource Identifier (URI).
Interaction with resources (located through their unique URIs) is accomplished using a uniform interface of the HTTP standard verbs (GET, POST, PUT, and DELETE). Also important in the interaction is the declaration of the resource's media type, which is designated
using the HTTP Content-Type header. (XHTML, XML, JPG, PNG, and JSON are some well-known media types.)
Resources are self-descriptive. All the information necessary to process a request on a resource is contained inside the request itself (which allows services to be stateless).
Resources contain links to other resources (hyper-media).” from microsoft
We don't need to change our class "HelloWorldService", so it should always be:
namespace MyWCFServices { /// <summary> /// Create a service class and implement service interface /// </summary> public class HelloWorldService : IHelloWorldService { public string GetMessage(string name) { return "Hello world from " + name + "!"; } public string GetPerson(string person) { return "Person name :" + person + "!"; } } }
While, the inteface "IHelloWorldService", should be modified.
using System.ServiceModel; //used for ServiceContract. it contains the types necessary to build Windows Communication Foundation (WCF) service and client applications. using System.ServiceModel.Web; namespace MyWCFServices { [ServiceContract] public interface IHelloWorldService { [OperationContract] [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/XML/{name}")] string GetMessage(string name); [OperationContract] [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/JSON/{person}")] string GetPerson(string person); } }
The content of "HelloWorldService.svc" should always be :
<!--Host web service--> <%@ServiceHost Service="MyWCFServices.HelloWorldService" %>
And then we should modify the web.config of "HostDevServer"
<?xml version="1.0" encoding="utf-8"?> <!-- Pour plus d'informations sur la configuration de votre application ASP.NET, consultez http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <!--Root node of config file--> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true" /> </system.webServer> <system.serviceModel> <!--Top node of WCF Service--> <behaviors> <serviceBehaviors> <!--Specify the bahaviors of a service--> <behavior name="MyServiceTypeBehaviors"> <!-- httpGetEnabled Enable other programs locate the metadata of this web service, client applications can't generate proxy and use web service without medatadata--> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="REST"> <!-- Important --> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <services> <!--List hosted WCF Services in this web site--> <!--Each service has its name, behavior and endpoint--> <service name="MyWCFServices.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors"> <!--Here wsHttpBinding should be replaced by webHttpBinding for REST Service, and behaviorConfiguration should be "REST" as defined in <endpointBehaviors>--> <endpoint address="" binding="webHttpBinding" behaviorConfiguration="REST" contract="MyWCFServices.IHelloWorldService"/> <!--this endpoint is for metadata exchange--> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> </system.serviceModel> </configuration>
We need to run the service in "HostDevServer" before we test in browser.
Firstly we'll test the first method "GetMessage",
Then, we test the second method "GetPerson",
I hope this helps! Enjoy coding!
reference:
http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide
http://msdn.microsoft.com/en-us/magazine/dd315413.aspx
http://en.wikipedia.org/wiki/Representational_state_transfer
四、指针
造成内存泄露的大多原因都是因为分配了空间但是没有进行释放的结果。但是这样并不会引发错误
一般来说,解决这个问题的有很多种方法,比如com、boost的智能指针,都在某一种情况下对这种问题提供了解决方案。下面来探讨两种情况的指针
但我们可以建立一个自己的smart point,同时也需要考虑三种情况:
1.是否允许对smart point进行复制,如果是,在smart point中的多份拷贝中,到底有哪一个负责删除它们共同指向的对象(com是最后一个)
2.smart point是否表示指向一个对象的指针,或者表示指向一个对象数组的指针(即它应该使用带方括号的还是不带方括号的delete操作符)
3.smart point是否对应于一个常量指针或一个非常量指针
出于上述的三个情况,有以下两种smart point可以满足:
1.引用计数指针(又称共享指针,也就是com中的smart point)
2.作用域指针
这两种smart point的不同之处在于引用计数指针可以被复制,而作用域指针不能被复制。但是,作用域指针的效率更高。
引用计数指针:
scpp_refcountptr.h:
#ifndef __SCCP_SCOPEDPTR_H__ #define __SCCP_SCOPEDPTR_H__ #include "scpp_assert.h" namespace scpp { template <typename T> class RefCountPtr { public: explicit RefCountPtr(T* p = NULL) { Create(p); } RefCountPtr(const RefCountPtr<T>& rhs) { Copy(rhs); } RefCountPtr<T>& operator = (const RefCountPtr<T>& rhs) { if (ptr_ != rhs.ptr_) { Kill(); Copy(rhs); } return *this; } RefCountPtr<T>& operator = (T *p) { if (ptr_ != p) { Kill(); Create(p); } return *this; } ~RefCountPtr() { std::cout << "kill" << std::endl; Kill(); } public: T* Get() const { return ptr_; } T* operator ->() const { std::cout << "in this" << std::endl; SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer."); return ptr_; } T& operator *() const { SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer."); return *ptr_; } private: void Create(T* p) { ptr_ = p; if (ptr_ != NULL) { refCount_ = new int; *refCount_ = 1; } else { refCount_ = NULL; } } void Copy(const RefCountPtr<T>& rhs) { ptr_ = rhs.ptr_; refCount_ = rhs.refCount_; if (refCount_ != NULL) { ++(*refCount_); } } void Kill() { if (refCount_ != NULL) { if (--(*refCount_) == 0) { delete ptr_; ptr_ = NULL; delete refCount_; refCount_ = NULL; } } } private: T* ptr_; int* refCount_; }; } // namespace scpp #endif // __SCCP_SCOPEDPTR_H__
测试代码(vs2012+win7环境):
// debug.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "scpp_vector.h" #include "scpp_array.h" #include "scpp_matrix.h" #include "algorithm" #include "scpp_types.h" #include "scpp_refcountptr.h" #define STUDENTAGE 10 class Student { public: Student(int age) : age_(age) { } void ShowAge() { std::cout << "my age is : " << age_ << std::endl; } private: int age_; }; int _tmain(int argc, _TCHAR* argv[]) { scpp::RefCountPtr<Student> smartPoint(new Student(STUDENTAGE)); scpp::RefCountPtr<Student> smartPoint2; smartPoint2 = smartPoint; //@test:赋值操作符 smartPoint = NULL; smartPoint2->ShowAge(); scpp::RefCountPtr<Student> smartPoint3(smartPoint2); //@test:拷贝构造函数 smartPoint2 = NULL; smartPoint3->ShowAge(); scpp::RefCountPtr<Student> *smartPoint4; //@test:引用 smartPoint4 = &smartPoint3; smartPoint4->Get()->ShowAge(); Student studen3 = *smartPoint3; //@test:Get() studen3.ShowAge(); smartPoint3 = NULL; Student *student4 = new Student(STUDENTAGE); //@使用方式 scpp::RefCountPtr<Student> smartPoint5; smartPoint5 = student4; smartPoint5->ShowAge(); return 0; }
作用域指针:
如果不打算复制智能指针(因此拷贝构造函数和赋值操作符被声明为私有),只是想保证被分配的资源将被正确地回收时使用这种方式,将会减少计数指针保存技术的int*的空间
scpp_scopedptr.h:
#ifndef __SCCP_SCOPEDPTR_H__ #define __SCCP_SCOPEDPTR_H__ #include "scpp_assert.h" namespace scpp { template <typename T> class ScopedPtr { public: explicit ScopedPtr(T* p = NULL) : ptr_(p) { } ScopedPtr<T>& operator = (T* p) { if (ptr_ != p) { delete ptr_; ptr_ = p; } return *this; } ~ScopedPtr() { delete ptr_; } T* operator -> () const { SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer."); return ptr_; } T& operator * () const { SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer."); return *ptr_; } T* Release() { T* p = ptr_; ptr_ = NULL; return p; } private: T* ptr_; ScopedPtr(const ScopedPtr<T>& rhs); ScopedPtr<T>& operator = (const ScopedPtr<T>& rhs); }; } // namespace scpp #endif // __SCPP_SCOPEDPTR_HPP_INCLUDED__
测试代码(vs2012+win7环境):
#include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "scpp_vector.h" #include "scpp_array.h" #include "scpp_matrix.h" #include "algorithm" #include "scpp_types.h" #include "scpp_refcountptr.h" #include "scpp_scopedptr.h" #define STUDENTAGE 10 class Student { public: Student(int age) : age_(age) { } void ShowAge() { std::cout << "my age is : " << age_ << std::endl; } private: int age_; }; int _tmain(int argc, _TCHAR* argv[]) { scpp::ScopedPtr<Student> smartPoint(new Student(STUDENTAGE)); //@test:构造函数 smartPoint->ShowAge(); scpp::ScopedPtr<Student> smartPoint2; //@test:实体类的赋值操作 Student *student = new Student(STUDENTAGE); //@使用方式 smartPoint2 = student; smartPoint2->ShowAge(); //@test:重载-> (*smartPoint2).ShowAge(); //@test:重载* scpp::ScopedPtr<Student> *smartPoint3; //@test:Release() smartPoint3 = &smartPoint2; Student *students2; students2 = smartPoint3->Release(); //释放smartpoint保存原来的地址 students2->ShowAge(); return 0; }
综合两个smart point的例子,使用方式都是“每次使用new操作符创建一个对象时,立即把结果赋值给一个智能指针”。
以上的两个smart point其实都没解决一个问题,就是当我们的对象是const的情况,怎么办?分析一下这种情况,传入smart point的对象是一个const,这以为这里面的一些成员变量是无法修改的,所以有了下面的一种半智能的smart point:
scpp_ptr.h:
#ifndef __SCCP_PTR_H__ #define __SCCP_PTR_H__ #include "scpp_assert.h" namespace scpp { template <typename T> class Ptr { public: explicit Ptr(T *p = NULL) : ptr_(p) { } T* Get() co