Visual Basic For C++ Programmers
Visual Basic For C++ Programmers
By Chris Sells
Although I have been programming with and teaching C++ since I learned it by reading the
CFRONT release notes, I also have a love for Visual Basic. Modern versions of Visual Basic are
remarkably similar to C++, in syntax and capabilities. So, for those hardcore types that hate VB
without taking the time to look at it, here is a tour of Visual Basic from a C++ programmer's point
of view.
To speed along this transition, let's write a VB program. Insert a Module into your new VB Project and enter the following code:
Sub main()
MsgBox "Hello, Visual Basic", vbOK, _
"<insert message box title here>"
End Sub
As you can see, the entry point for a VB program is just like that of a C++ program: main(). One
difference you've probably noticed is the lack of semicolons. Instead, the end of the line marks
the end of a VB statement. If you have a long statement (like the MsgBox statement in the
example above), use the _ to split it between two lines.
Before you can run this program, you will need to either remove the Form1 from the project or
change the Startup Form from "Form1" to "Sub Main" in the Options dialog. To run the program,
press the VCR style "Play" button on the toolbar or press F5. At this point, your program is being
run by the VB interpreter. If you'd like to make it into a standalone application, choose the Make
EXE File option from the File menu. Now you can double-click on it from the shell and it will run
just like a real Win32 application (because it is).
Data types
To write real programs, you must use variables. You just turned on "type checking," so you will
need to know what types you can use. Visual Basic has the integral types you would expect: byte,
integer (2-byte signed), long (4-byte signed), single (4-byte real) and double (8-byte real). In
addition, it also has Boolean, currency and date types. Instead of characters, Visual Basic has a
string data type. It grows and shrinks as necessary and comes with a full range of operations for
comparison, searching and sub-string manipulations.
To explicitly declare a variable of a specific type, use the "dim" statement (which stands for
dimension). Uninitialized variables start with an initial value of "zero," e.g. integers start as zero,
strings start as "", etc. Figure 1 is an example of using types in Visual Basic.
User-defined types For those occasions when you cannot use one of the built-in data types, Visual Basic allows the definition of a
User-Defined Type (UDT) using the type statement. The elements of a UDT can be any VB type including another UDT. The following is an
example of defining and then using a UDT in VB:
Type MyNumber
n As Integer
s As String
End Type
Sub main()
Dim num As MyNumber
num.n = 1340
num.s = "Thirteen hundred forty"
End Sub
A UDT is the equivalent of the C++ structure with one difference: a UDT cannot have a circular
reference to an element of its own type. This would require a pointer, which is one type that VB
does not have (although it does have references, which we'll see later). The lack of pointers is
good news because the presence of a pointer can lead to memory management, which leads to
more code, which leads to bugs, which leads to maintenance, which leads to evenings and
weekends away from your family and friends. Because it does not support pointers, VB is able to
handle memory management for you. The problem is that without pointers, it is very hard to have
a dynamic collection. One way to solve this problem in VB is with an array.
Figure 2 is an example of declaring and using static and dynamic arrays. Notice that arrays can
be declared with an optional lower bound (the default is zero). The lower and upper bound of an
array can be determined at runtime using the LBound() and UBound() functions. A syntax change
you should notice is that array elements are declared and accessed using parentheses instead of
brackets.
Constants Under C++, arrays must be declared using a constant size. To avoid magic numbers, we use either #define statements,
const variables or enumerations. All of these are also available under VB (although enumerations are available only under Visual Basic 5.0
or better). The VB Const statement and Enum statement work exactly like their C++ counterparts, but the #Const statement is a bit
different. The VB "preprocessor" (and I use that term loosely) isn't as flexible as the C++ preprocessor. Instead of allowing arbitrary
replacement of code via the #define statement, VB only allows constant definitions via the #Const statement. This statement is typically
used for conditional inclusion of code within #If-#ElseIf-#Else-#End If blocks. In addition to the #Const values your programs define, VB
provides the predefined constants Win16 and Win32 for source code compatibility between 16-bit and 32-bit Windows platforms. The
following code shows an example of using the VB preprocessor as well as the Const and Enum statements:
#Const DEBUGMODE = 1
Const MAX_INTS As Integer = 4
Enum Bits
bit0 = &H1 ' Hex notation
bit1 = &H2
bit2 = &H4
bit3 = &H8
End Enum
Sub main()
#If DEBUGMODE Then
MsgBox "Debugging..."
#End If
Variants If you cannot decide which type you would like under C++, use a union. VB doesn't have
unions, but it does have variants. A variant can hold data of any type and it will convert itself as
needed. This self-conversion includes self-promotion. If you have a variant holding data of one
type and the operation you perform on it would normally overflow the range of that type, the
variant will be promoted to the next largest type, e.g. a single will be promoted to a double.
In addition to holding normal data, variants have two special values. Empty means that the
variant hasn't been initialized yet, and Null means that the Variant holds no data. Null is especially
valuable because it's distinguishable from zero (unlike in C++ where zero and NULL are the
same).
If you need to determine what type a Variant is, the VarType() function returns one of the Variant
type constants, like vbNull or vbInteger. If you would rather have a string description of a Variant
type, you can use the TypeName() function. Figure 3 shows an example of using a Variant for
different data types and how the VarType() and TypeName() functions can be used.
Objects The single best thing about Visual Basic is its support for classes and objects. Just like
C++, VB can support private and public member functions (called methods) and member data
(called properties). Creating a new class is simply a matter of adding a new class module to your
VB project and adding properties and methods.
The Object type, and user-defined class types, are just object references. Creating an object is
accomplished by setting the result of the New operator to an object reference variable. An object
is destroyed when there are no more references to it. A reference to an object will go away
implicitly when an object reference variable goes out of scope or explicitly when the object
reference variable is set to the special value Nothing. Figure 4 is an example of declaring a user-
defined class and Figure 5 is an example of using it.
Just like C++, VB supports constructors, destructors, polymorphism, runtime type identification
(like the C++ dynamic_cast operator), encapsulation, abstraction and inheritance (although only
VB5+ and only inheritance of interface). Unlike C++, all VB classes can be exposed for use in
other languages and other processes (even across the network). The ability to expose classes is
a direct result of how VB provides its objects: COM. All VB objects are COM objects, even the
intrinsic objects like Form, Button and Label. This makes VB the first direct-to-COM compiler.
There is a lot more to classes and objects in VB. A full description of VB's support for objects and
COM is beyond the scope of this article.
Flow control
You can only get so far using just variables. Eventually, you'll need to make a decision or change
the flow of your program in some way. Just like C++, VB supports if statements and case
statements; for-loops, do-loops and while-loops; and goto statements. All of them work similarly to
their C++ counterparts except that some are more flexible. Specifically, the Case statement
allows testing for ranges and Boolean expressions in addition to simple equality. There is no need
for a break because Case statements never fall through (when was the last time you meant that
to happen in C++?).
To make a decision, you're going to need comparison and logical operators. The comparison
operators are =, <=, >=, <, > and <> (inequality). The logical operators are And, Or and Not and
they are equivalent to the &&, || and ! operators in C++. For bit-wise operations, VB reuses the
logical And, Or and Not as well as providing the Eqv (equivalence), Imp (implies) and Xor
(exclusive or) operators.
VB supports one additional flow control construct that C++ doesn't: for each-loops. Since arrays
(and other kinds of collections) can support an index lower bound that is not zero, and since you
often are not concerned with what the index is anyway, VB provides the for-each construct to
iterate over each element without referring to an index. Figure 6 shows an example of the for-
each loop as well as the other flow control constructs available in VB.
Functions and procedure routines live in modules. Routines marked as Public can be accessed
from any module while those marked as Private can only be accessed inside the module. To call
a Public routine in one module from another, prefix the name of the module and a dot before the
name of the routine, e.g. Module1.MyFunc. If you imagine a VB module as a C++ namespace,
you'll have it.
Parentheses Calling a routine is a little different in VB than in C++. Do not wrap your argument
list in parentheses if you are calling a procedure(unlike C++). If you are calling a function and you
would like to handle the return value, wrap your argument list in parentheses (just like C++).
However, if you're calling a function just as if it were a procedure, i.e. you're not handling the
return value, call it like a procedure by not using parentheses. While this may seem strange to the
average C++ programmer, it all boils down to one simple rule: If you need the return value from
a routine, use parentheses; otherwise do not.
Why is all of this such a big deal if Visual Basic notifies you of errors as you type? Because other
uses of the parentheses are valid when calling functions and procedures that have nothing to do
with wrapping lists of parameters. For example, wrapping a single parameter in parentheses
changes how the parameter is passed. If it's a parameter of any type besides Object, the
parameter is changed from pass-by-reference to pass-by-value. On the other hand, if it is a
parameter of the Object type, the object's default property is sent instead of a reference to the
object. These can be handy features to have, but unless you know about them, they can cause
different behavior than you would expect.
Parameters Once you have figured out how the parentheses work, you are now qualified to
actually pass parameters. Function and procedure routines both take parameters in the same
way, i.e. by value or by reference. This is specified using the ByVal or ByRef modifiers in front of
the parameter. If no modifier is specified, the default is by reference. Be careful. The default
behavior is to allow routines to change variables passed as parameters. This is certainly different
than in C++, so it's a good idea to be explicit about how parameters are passed into your
routines.
In the same way that C++ supports default arguments, VB supports optional parameters. Variant
parameters can be marked as Optional in the argument list. Unlike C++, however, in VB initial
values for missing parameters must be set explicitly in the function or procedure body. To
determine whether a parameter was passed or not, use the IsMissing() function on each optional
parameter.
For situations in which a fixed number of arguments are not enough, VB also supports a variable
number of parameters. A parameter list that ends in an array of Variants marked as a
ParamArray, will take zero or more optional parameters. These values can be passed by value
only (although it is illegal to mark them ByVal).
Returning Once the flow of control reaches the end of a routine, it will return to its caller. A
procedure or a function can be ended early by using the Exit Sub or Exit Function statements
respectively, just like the return statement in C++. Unlike the return statement, however, in VB a
function's return value is set by using the name of the function on the left hand side of an
assignment statement, just like assignment to a variable. A function's return value that is not set
before the function is ended will default to "zero" just like an uninitialized variable.
Figure 7 shows an example of defining and using functions and procedures in Visual Basic.
Error handling
Just as in C++, the preferred error handling technique in VB is via exceptions. The global Err object has a Raise() method that takes a user-
defined error number and some optional parameters like the description and source of the error. When an error occurs, a function or
procedure routine can halt execution by raising an exception like this:
Sub CallMe()
Err.Raise 1, "CallMe() function", "Test error"
End Sub
To catch the exception, the caller must proceed the call to the routine with an On Error statement specifying whether to resume on the next
line of code or to go to a label in the routine. When an exception is thrown, the caller can get at the arguments to the Raise() method via the
properties of the Err object like this:
Sub main()
' Handle the exception
On Error GoTo HandleException
CallMe
HandleException:
MsgBox Err.Description, vbOK, _
"Error #" & Err.Number & " from " & Err.Source
However, isn't VB much slower than C++? While it is true that interpreted VB is slower than
compiled C++, I believe the clunky nature of most of the VB programs have more to do with who
is developing them than the features of the language. Even if you were a journalism major, it is
not likely that you are qualified to optimize code in any language. VB is so much easier that you
do not need a Computer Science degree to get your work done, but it certainly helps if you want
to get your work done well.
Once VB can be compiled (any day now), won't it be nice to spend your weekends at home?
Figure 1 - Using VB types
Sub main()
' Declare and initialize a string.
Dim sGreeting As String
sGreeting = "Greetings, "
' If statement
If i < 2 Then
MsgBox "Before 2..."
ElseIf i > 6 Then
MsgBox "Past 6..."
Else
MsgBox "In the gooie center."
End If
Next i ' Index name is optional, but helps catch errors
End Select
If i > 2 Then
' Early exit from Do loop
Exit Do
End If
i = i + 1
Loop While i <= UBound(ints)
If i > 3 Then
' Early exit via GoTo
GoTo FinalClear
End If
Loop Until i > UBound(ints)
End Sub
Figure 7 - Functions and Procedures - Option Explicit
Sub MsgBoxN(ByVal s As String, Optional ByVal n As Variant)
' Check for missing optional parameters
If IsMissing(n) Then
n=1
End If
Dim i As Integer
For i = 1 To n
MsgBox s
MsgBox s
End Sub
Sub main()
Dim bSuccess As Boolean
bSuccess = CallProcs
End Sub