Tuesday, November 3, 2009

Be Advised: C++ vs Delphi

While thinking about what knowledge would be of most use to the rest of programmerdom, I realized that an objective, non-biased, experienced, comparison between C++ and Delphi would provide valuable information to one and all, that all may be more educated as to the tradeoffs of these languages, their pros and cons, and perhaps be able to glean valuable insight to pass on to the next generation of programming languages.

I hear that everybody loves flamewars. If you’ve come for that, please leave now.

Still here? Ok, nice. If you’re like me, you know that anyone who is wedded to programming language X, has not spent enough time in their lives programming nor studying programming languages, to have serious experience with or understanding of programming languages. However, if you are one who has come for an experienced comparison of C++ and Delphi, well, you will not have wasted your time (inasmuch as I’m not restating what you already know). Let me just give 1 caveat: I have much more experience with Delphi than with C++, so I may have left a couple of advantageous features of C++ out. If I do so, please remind me, and I will be sure to include such (provided they meet the criteria of being exclusive, marked advantages.) Now, enough with the fluff, let’s get down to the meat. The following lists features that vary from Delphi to C++, listing the winning language:

FeatureWinnerExplanation
ClosuresDelphiC++ just doesn't have closures. Closures are an advantageous way to organize long procedures of code into smaller, more reusable pieces.
Operator OverloadingC++Delphi doesn't have this feature. Operator overloading is useful for terse arithmetic libraries over different kinds of quantities, such as intervals, bignums, and others, instead of having to invoke a bunch of method calls by name. In addition, expressions can be semantically overloaded and more reusable via OOP.
InterfacesDelphiC++ doesn't have interfaces. Interfaces are like mixins without implementations: they provide a description of a set of methods that a class would need to implement to be compatible with the interface. Subroutines can use interfaces to be more generic and reusable, by accepting, as a parameter, any object that implements a specified interface. Classes in Delphi can implement as many interfaces as they like. This provides a simple alternative to multiple inheritance.
Multiple InheritanceC++Delphi just doesn't have multiple inheritance. Multiple inheritance is where an object can inherit fields and methods from more than one base class. In practice, this is very complicated and is usually overkill, but for those situations in which it makes sense, C++ provides this alternative.
PropertiesDelphiIn C++, one must use getters and setters to write to the properties of a class. In Delphi, one describes properties, and can direct reading and writing to either a field or a getter and setter method, or describe whether a property can even be read from or written to. In addition, one can reference a property via the dot notation. e.g. "GoButton.Enabled" and use such an expression for reading and writing, without having to directly invoke getters and setters. This provides better abstraction.
Module SystemDelphiIn C++, you have header files and C++ files. The header file declares what code is available to other C++ files. The preprocessor is assigned with the task of providing each C++ and header file with knowledge of its dependencies. In Delphi, a module is a single file called a unit. The unit lists what code is public to other units (called the interface of the unit), as well as housing the implementation of the public declarations. Units lists their dependency on other units via the "uses" clause. In addition, Delphi provides optional initialization and finalization sections, so that the unit can initialize or free any internal state it uses. These features all provide for a much more robust seamless module system, giving each unit airtight encapulation facility. Of course, Delphi is a member of the Pascal family of languages, which are all known for their robust module systems.
Constructors and Stack ObjectsC++C++ has a standard system for copying objects, in addition to the normal constructor used for creating objects. This streamlines this utility. In addition, C++ then provides a way to declare object variables that are automatically created and managed on the stack. This provides better abstraction for temporary helper objects, which can then be treated as data types. In Delphi, however, all objects are created on the stack, and must be explicitly created and freed. Object variables are actually assignable, nullable references to object instances. Also, Delphi does not have a built-in system for copying objects or assigning their values around, although there is a standard method convention used for assigning objects to each other.
Templates and Generic ClassesC++Delphi does not have templates, nor does it have generic classes. This means that algorithms and data structures must be implemented differently for objects and primitive types. C++ provides templates, which allow any piece of code to be reused for different, but compatible, types, primitive or not.
Method PointersDelphiDelphi provides well-developed facilities for managing pointers to methods and subroutines. This comes in handy for event-handling code and other related uses. C++ on the other hand, is very messy, requiring one to get into some hairy types. Generally, using pointers to methods or subroutines, is not recommended. Instead, C++ relies on templates to facilitate the coupling of objects to event handlers.
Error MessagesDelphiC++'s error messages are often cryptic and do not provide intuitive or simple feedback to the programmer. Delphi always provides simple, direct error messages (although both languages use programming-centric terminology).
Encapsulated Class DefinitionsC++C++ allows one to declare a class inside a class. This is useful in some cases, so C++ provides the option. As far as I know, Delphi does not.
HackerinessC++C++ is more all-around hacker-frendly, and relies more on the use of symbols and operators, making it, in comparison to natural language, more cryptic. Delphi uses alot more english words and alot less symbols, for its code. Of course, experience with either, will render this difference negligible, but hackers tend to enjoy symbols more.
ReferencesC++C++ has references as a type. References are a more abstract version of pointers, and have lean implementations. Thus, they can come in handy for simplifying code and making it more readable. Delphi, while allowing one to pass parameters around by reference, does not have a reference type -- just pointers.
Dynamic ArraysDelphiDelphi has built-in, leanly-implemented, runtime-resizeable arrays of any dimension. These can come in handy in many situations, since Delphi lacks generics. C++ has no such thing, instead relying on its generics to achieve the same functionality.
Strings and String ManagementDelphiDelphi has built-in, leanly-implemented, memory-managed strings. Thus, using strings in Delphi is a breeze. The same is not so true for C++, but it covers most all of the ground, in ease-of-use, with its String class.
Compilation TimeDelphiDelphi was designed to compile fast, and to only compile the units that have changed since their last compile. Thanks to its module system, this is more easily achievable. In practice, this means that the compile-run cycle is quick, since the compiler will only compile the units you make changes to.
In-block VariablesC++C++ allows one to declare variables anywhere inside a block of code. This is much more convenient for writing code than in Delphi, which requires all variables to be declared in the declarations section, preceding the implementation blocks of code. Although one might argue that there's a trade-off between more readable code and more writable code. But I'd prefer C++'s choice on this one.
VariantsDelphiDelphi provides a primitive type called a Variant, which is simply a data type that can only any other primitive type (no compound types, pointers, objects, or dynamic arrays). This can be useful in situations where one would otherwise have to write lots of type-handling code. This type as evolved into the OLEVariant type, which allows Delphi programmers a choice when coding for COM and OLE automation, between early-bound and late-bound style.
SetsDelphiDelphi's equivalent to C++'s enumeration type, is much more well-abstracted. Delphi provides set union and difference operators.
Open Array ParametersDelphiIn addition to dynamic arrays, Dephi provides a way to pass arrays as parameters. It even provides a notation for declaring array-literals as parameters. e.g. "PrintLn(["hi",a,"two",x])" This is extremely handy when developing and using DSL-like libraries, such as parsers. C++ doesn't quite have this functionality.
"with" statementDelphiC++ does not have "with" statements. "With" statements are very useful for unraveling repeated object references and putting the referenced object's properties and methods automatically in the local scope. This seems like a trivial convenience, but we'll see later on why it's such an important ingredient to the repertoire of delphi's constructs.

Conclusion

So, after looking over this list of features, there's a couple of patterns that stand out -- consistent language design choices made. Delphi is intended to be an applications programming language, seeking to provide for more abstraction in many common areas -- strings, modules, open array parameters, late-bound COM programming. This is a common thread running through the design decisions of Delphi. Don't get me wrong, it's also intended to create programs of competitive efficiency with C++, but the point is that Delphi is focused on providing more abstraction for applications programmers. C++ is a systems programming language, designed to not trade a single bit of efficiency away for abstraction. It tries to do what it can for abstraction, but the guiding principle, indeed, the constraint, upon C++, is that there is nothing in the language that prevents the programmer from hand-optimizing efficiency. Language design choices are a different subject altogether, though. Just remember that language differences don't necessarily imply general superiority or inferiority. C++ is a better systems language, and Delphi is a better applications language. Each has its own optimal role.

No comments:

Post a Comment