中文版 | English

网站首页 | 个人作品 | 博客 | 给我留言 | 经典分享 | 友情链接 | 黑白人生


From C++ to PHP[by Philippe Lachaise]

A strong C++ background can be an invaluable asset when you are learning PHP scripting. Conversely, having a naive approach to PHP might get you into trouble when things get complex."Why are you wasting your time dabbling with PHP?"Such was the question a friend and former colleague of mine asked me a while ago. His judgment reflects a still widespread conception that, in spite of its success, PHP is not a serious language, at least not for enterprise application development.At the time we were working together, I happened to enjoy the reputation of in-house C++ expert. To my friend, my current strong involvement in PHP just didn't add up with my C++ past and, according to him, I should have been spending my energy on mastering Java or .NET or perhaps both.Being immune to marketing noise sometimes helps in detecting an important phenomenon. PHP's rise in popularity is one example. Oddly enough, a strong C++ background happens to be an invaluable asset when you are learning this scripting language.The Network is at Last Becoming the ComputerAfter having been just a catch-phrase for a long time, this famous slogan is becoming a truth. People are realizing that there is much to be gained by leveraging internet technology for all kinds of networked applications and, if rich clients are still an option, they will be built on new Web technology. Let us reflect about the software development implications.Leaving aside genuine distributed applications and Web services for the moment, let us consider the usual dynamic Web site, which is a transposition on the internet of the good old client-server application.Reboot is not an option: With visitors accessing your Web site or intranet at any time of the day or night, your application code is not allowed to crash. It may produce errors (let's be humble and realistic), but it simply cannot crash. This all but rules out C++ for Web development. I am not saying I would not try to do it, but I would not trust anyone to do it on my behalf. It boils down to the same thing: impracticality.Born-Again CoderNow, with the IT job market shifting rapidly from PC to Web, how am I going to carry on using my hard-won expertise of object programming with C++?Here comes PHP. At first a scripting language looks suspicious. When you are used to compilers, scripts really feel like toys. Loose typing lets variables bend in all directions, and it must be terribly slow....On second thought, the assembly language of the Web is no longer binary code—it is text markup. And text calls for scripting.The pressing question then becomes: how do I reinvest all my valuable expertise with compiled languages into a script-dominated context?So, let us forget prejudice and give it a try. We will not abandon object methodology. Every time I tried cutting corners by going back to quick-and-dirty coding, I ended up having to backtrack and start again with objects. So, satisfying object support will be a make-or-break condition.The Very Beginning: Do-Re-MiA very good place to start, as the song goes. Let us write a class:
class MyClass // C++ like comments are supported{}
Ring a bell? C++ would complain about the missing semi-colon, but never mind. Good, we have a class; let us now unfold it while pointing out differences and similarities as we go along. Most differences are merely syntactical, and only a few go deeper.To keep things simple, we will restrict our analysis to PHP4.
// Notice "extends" keyword. All inheritance is public anyway. class MyClass extends BaseClass{ var $_dow; // For some historical reasons class var $_ray; // attributes are declared with "var" var $_me;  // keyword (ours is not to reason why) // Constructor, like in C++ is a function named like class // "function" keyword is mandatory. No return type. function MyClass($param)  {  // Explicit call to parent class constructor  $this->BaseClass($param); } // There is no ~MyClass() // Return types are not specified, reference (&) is. function & get_note($note) {  // We assume $note is a string (could check with is_string())  switch ($note) // Highly familiar switch statement...  {   case 'dow': // ... apart from its understanding strings !    return $this->_dow;   case 'ray':    return $this->_ray;   case 'me':    return $this->_me;_me;   default:    break;  }  // Undefined return values are your responsibility !  }}
At first, syntactical differences may be irritating, but that will soon fade. You have to remember that PHP is interpreted, so if the "$" prefix makes variable lookup faster or $this-> is necessary to disambiguate between local/global scope and class member, it is still a small price to pay and does not introduce conceptual differences with regard to C++. A bigger difference is the lack of a destructor. This issue is common to all garbage-collected languages. As far as the programmer knows, object destruction is not deterministic, so you have to release whatever resources you owe to the system in an explicit manner. Unlike in C++, you cannot rely on the destructor to "remember" to clean up after you. Since you seldom own system resources (even database connections are released at the end of the HTTP request), it is not a big issue.The constructor is pretty much the same as in C++, except for the absence of automatically nested calls to the base class constructor. In other words, you must call the base class constructor explicitly. So the first thing to do when writing a derived class is to write the $this->BaseClass(); statement before you forget (and before it comes back to haunt you).Let us look at the switch before we leave low-level concerns that are more reminiscent of C than of C++: PHP accepts strings as switch argument whereas the C switch only accepts native types—integer or pointer. A rather nice change, really.So Object is Possible...If You are CarefulThe longer I have been acquainted with PHP, the more I have come to realize that—even though it differs from C++ by hundreds of details—there is no conceptual gap between the two languages such as would render good practices honed by years of C++ inoperative.One must remember that object support came as an afterthought to PHP (the story goes that it was added during one night by Zeev Suraski and Andy Gutmans), so its implementation is not foolproof and will let you do things that will result in loss of sleep.On the other hand, your C++ training has provided you with the one thing that will help you avoid object PHP booby traps. C/C++ has taught you to think like a compiler, feel what must be going on in the memory, decipher cryptic error messages, and guess the compromises made by language designers—keeping in mind, of course, that under the hood PHP is all made of C.So one sure thing is that the deeper your understanding of C++, the easier it will be for you to use PHP à la C++.Navigating Uncharted Waters SafelyObject methodology encourages systematic practices. Some aspects of PHP are confusing and don't lend themselves well to object treatment. For instance, in PHP4 object assignment (operator =) copies the object to the left-hand value. The depth of shallowness of that copy is never clear and is usually irrelevant to the problem at hand. Just avoid the problem by making systematic use of references:
$objref=&$obj;
Unless you explicitly intend to clone an object, copying usually reveals a design flaw in your program and results in two (or more!) objects with more or less consistent states while they're supposed to stand for the same piece of data. This is an all-too-frequent waste of memory and a source of confusion. Just avoid it—until PHP5!Here again your C++ background should come to the rescue. Copy constructor annoyances must have taught you to keep things as simple as possible.I miss my templates and pointers to functions.
Next Steps
Discussion Forum: PHP on Oracle The Hitchhiker's Guide to PHP Open Source Developer Technology Center Troubleshooting Guide for Oracle + PHP PHP Scripting: The Growing Popularity of Footloose and Fancy-Free Code Get Started with Oracle + PHP Install Oracle, PHP, and Apache on Linux
I happen to be obsessively attracted by generics. Time is better invested in identifying and solving a category of problems once and for all than in writing nearly the same piece of code over and over. A wonderful, albeit sometimes arcane, feature of C++ is templates. Once you have realized how much work you may extract from the compiler by a judicious use of templates, it is difficult not to get addicted to them. In consequence, it makes adopting a language devoid of generics much less appealing.In fact, it is quite easy to use generics with PHP, using callbacks or code generation.Explaining the latter would require a full article or a book. Let us just mention that it can be easily implemented with PHP/XML technology.PHP callbacks are the conceptual equivalent of C pointers to functions. Whatever the language, they are to programming what verbs are to speech (variables being the equivalent of nouns, of course). The textbook example is enumeration: let us say you want to list a set of orders. The presentation code is not aware of whether data comes from flat files, XML, or a SQL query. All it has to do is call the enumerator, passing it a callback to handle resulting calls:
/*** Process one order independently of data source** @param $order_data mixed Whatever data is* @return boolean true if OK or false*/function print_order($order_data){ // Process order data (output one record for instance) echo ('<tr><td>'.$order_data.'</td></tr>'); return true;}/*** Enumerates order records through callback** @param $caller string Name of callback.*/function enum_orders($callback){ while (/* whatever it takes to retrieve one order */) {  // Here's one record, handling is up to caller.  if (!call_user_func($callback,$order_data))  {   break;  } }}// Now let's use it<?php enum_orders('print_order'); ?>
Now, we may want to mail the very same orders instead of just printing them. We simply need to change the callback to, say:
<?php enum_orders('mail_order'); ?>
OK, this is simplistic and we could do much better (invoke one object's method). The point is that callbacks are available, as in C++ (their consisting in a string rather than a pointer is immaterial as far as design is concerned).Callbacks are nice, but still they are a bit old hat, they're SDK-like, and they don't take much advantage of object capabilities. We can take them one step further and regroup them into interfaces. This calls for abstract classes. PHP does support this feature:
// C++class IMyInterface{public:  // Virtual methods declared with "=0" are abstract virtual void fun1(int  nParam) = 0; virtual void fun2(long lParam) = 0;}// PHPclass IMyInterface{ // Methods declared with "{}" are abstract function fun1($nParam) {} function fun2($lParam) {}}
Your interface defines a "contract" that you or someone else will fulfill by implementing the abstract class. The nice thing is that implementations will be replaceable like spare parts are—software components.When application logic starts scaling up (as it always does in the end), this style of programming can make the difference between rampaging complexity and continued control of a linear evolution.The next logical step is to use a class factory, but it would take us much further than intended.Now if, as I hope, reading these lines has whetted your appetite for object PHP, do visit www.reflexivecms.org. The XML/PHP framework that lives there goes one step further and beyond.Quick Comparative StudyThese cousin languages bear a strong resemblance as well as clearly distinctive traits:
C++ PHP
Class Class MyClass : public BaseClass {} class Class MyClass extends BaseClass {}
Inheritance Multiple Simple
Constructor MyClass() {} function MyClass() {}
Destructor ˜MyClass() {} None
Parameter Passing By value but widespread use of pointers make it equivalent to references (references are also supported). Passing objects by value by default has been making PHP the odd language out. PHP 5 will bring it in line with other object languages.
-> operator Pointer to class or struct member. Access to class member (would be "dot" in many languages, but dot is already string concatenation operator). Pointers are absent in PHP.
f()->g() calls Can be arbitrarily nested. Will be supported by PHP 5. Until then use saved returned value (a two-steps process)

$r=&f(); // step 1
$r->g(); // step 2
Type system Statically typed. Dynamically typed.
Strings Not a native type (ASCIIZ). Natively supported.
Arrays Static Dynamic— - Associative
Garbage collector None, ; manage memory the hard way. All system resources are garbage garbage-collected.
Preprocessor Very elaborate. Absent—define() supported.
Language level L3G with L4G-like libraries. L4G, sometimes strongly reminiscent of L3G.
Wrap-upHaving been "dabbling" with PHP for a year and a half, I have found that programming the network is not that different from programming the computer when using this language. Advanced programming practices can be easily transposed with a bit of care, and there is no built-in limitation nor performance penalty to using modern object approaches. Being experienced in C++ stops one from having a naive approach to PHP that might get you into trouble when things get complex. It also helps in understanding where the language is going with PHP5 and beyond.Getting acquainted with PHP was time well spent.
Philippe Lachaise (plachaise@virtualmice.net) started with IT in the mainframe environment of the mid-80s. Moving to specialized translation of computer software, he started programming seriously to build translation productivity tools. An early adopter of object technology, he has since had experience with various flavors of object application development. Now Lachaise learns and practices Web standards. To reconcile time-honored object development practices with Web constraints, he has recently been developing RefleXiveCMS, an XML/PHP application framework that aims at transposing to Web development more than ten years of C++ and componentware experience.

上一篇: ssdp简单服务发现协议
下一篇: php2cpp