Tangible Software Solutions

VB.NET and C++ Comparison and Equivalents


Equivalents were produced with the Free Edition of Instant C# (VB to C# converter) and the Free Edition of C# to C++ Converter.


Sized Array

C++ VB.NET
int myArray[2];

or:

int *myArray = new int[2];
Dim myArray(1) As Integer

Access Array Element

C++ VB.NET
x = myArray[0]; x = myArray(0)

Jagged Array

C++ VB.NET
int **myArray = new int*[2]; Dim myArray(1)() As Integer

Rectangular Array

C++ VB.NET
int myArray[2][3];

Dim myArray()() As Integer = { New Integer(2){}, New Integer(2){} }
VB.NET C++
Public Sub method(ByRef valueTypeParam As Integer, ByRef refTypeParam As Foo)
    ...
End Sub
public:
void method(int &valueTypeParam, Foo *&refTypeParam)
{
    ...
}
VB.NET C++
x = CBool(y)
x = CInt(y)
x = CChar(y)
x = CStr(y)

x = CType(myObject, FooType)
x = DirectCast(y, FooType)
x = TryCast(myObject, FooType)
x = static_cast<bool>(y);
x = static_cast<int>(y);
x = static_cast<wchar_t>(y);
x = static_cast<std::wstring>(y);

x = static_cast<FooType*>(myObject);
x = static_cast<FooType*>(myObject);
x = dynamic_cast<FooType*>(myObject);

In VB, the keyword 'From' is used to initialize collections during construction.

VB.NET C++
' List:
Dim myList As New List(Of Integer)() From {1, 2, 3}

' Dictionary:
Dim myD As New Dictionary(Of String, Integer) From {
    {string1, 80},
    {string2, 85}
}
// vector:
std::vector<int> myList = {1, 2, 3};

// unordered_map:
std::unordered_map<std::wstring, int> myD = {
    {string1, 80},
    {string2, 85}
};

Vectors (C++) and Lists (VB.NET)

C++ VB.NET
#include <vector>

void Vector()
{
    std::vector<int> myList;
    myList.push_back(1);
    int i = 1;
    myList[0] = i;
    i = myList[0];
}
Imports System.Collections.Generic

Sub Vector()
    Dim myList As New List(Of Integer)()
    myList.Add(1)
    Dim i As Integer = 1
    myList(0) = i
    i = myList(0)
End Sub

Maps (C++) and Dictionaries (VB.NET)

(std::map and SortedDictionary are also very close equivalents).

C++ VB.NET
#include <string>
#include <unordered_map>

void UnorderedMap()
{
    std::unordered_map<std::wstring, int> map;
    std::wstring s = L"test";
    map.emplace(s, 1);
    int i = map[s];
    i = map.size();
    bool b = map.empty();
    map.erase(s);
}
Imports System.Collections.Generic

Sub UnorderedMap()
    Dim map As New Dictionary(Of String, Integer)()
    Dim s As String = "test"
    map.Add(s, 1)
    int i = map(s)
    i = map.Count
    Dim b As Boolean = map.Count = 0
    map.Remove(s)
End Sub

Local Constant

VB.NET C++
Const myConst As Integer = 2 constexpr int myConst = 2;

Class Constant

VB.NET C++
Public Const myConst As Integer = 2 public:
static constexpr int myConst = 1;

Local Variable

VB.NET C++
Dim myVar As Integer = 2 int myVar = 2;

Inferred Types

VB.NET C++
Option Infer On
...
Dim myVar = 2
auto myVar = 2;

Shared/Static Field

VB.NET C++
Public Shared S As Integer public:
static inline int S = 0;

Read-Only Field

VB.NET C++
Public ReadOnly R1 As Integer = 2
Public ReadOnly R2 As Foo = New Foo()
public:
const int R1 = 2;
Foo *const R2 = new Foo();

VB Static Local Variable

VB.NET C++
Sub Method()
    Static s As Integer
    s += 1
End Sub
public:
void Method()
{
    static int s = 0;
    s += 1;
}

The implementation of the 'Dispose' method in the IDisposable interface can be converted to a C++ destructor, but this is not exactly equivalent.

VB.NET C++
Class Foo
    Implements System.IDisposable

    Public Sub New()
        Me.New(0)   ' call to other constructor
    End Sub
    Public Sub New(i As Integer)
    End Sub

    Public Sub Dispose() Implements System.IDisposable.Dispose
    End Sub

    Protected Overrides Sub Finalize() ' 'finalizer' method
    End Sub
End Class
class Foo
{
public:
    Foo() : Foo(0)   // call to other constructor
    {
    }
    Foo(int i)
    {
    }

    ~Foo()   // destructor
    {
    }

private:
// There is no equivalent in C++ to finalizer methods:
    void Finalize()
    {
    }
};
C++ VB.NET
int/signed int
long/long int/signed long/signed long int

long long/long long int
signed long long/signed long long int

short/short int
signed short/signed short int

unsigned/unsigned int
unsigned long/unsigned long int

unsigned short/unsigned short int
unsigned long long/unsigned long long int

bool
char/wchar_t
signed char
unsigned char
float
double/long double
std::wstring (no C++ language built-in type)
std::any (C++17) or void * (no C++ language built-in type)
No C++ language or standard library equivalent
No C++ language or standard library equivalent
Integer
Integer (may convert to 'Long' on some systems)

Long
Long

Short
Short

UInteger
UInteger (may convert to 'ULong' on some systems)

UShort
ULong

Boolean
Char
SByte
Byte
Single
Double
String
Object
Decimal
Date

A C++ function pointer corresponds to a VB.NET delegate.

C++ VB.NET
// C++11 syntax:
using MyDelegate = std::function<void (int i)>;

// before C++11:
using MyDelegate = void (*)(int i);
Public Delegate Sub MyDelegate(ByVal i As Integer)

Implicitly-Typed Enum

VB.NET C++
Public Enum FormMode
    EditMode
    NewMode
End Enum
enum class FormMode
{
    EditMode,
    NewMode
};

Explicitly-Typed Enum

VB.NET C++
Public Enum FormMode As Byte
    EditMode
    NewMode
End Enum
enum class FormMode : unsigned char
{
    EditMode,
    NewMode
};

The most significant difference between VB and C++ exception handling is that C++ has no 'finally' clause.

VB.NET C++
Try
    ...
Catch x As FooException
    ...
Finally
    ...
End Try
try
{
    ...
}
catch (const FooException &x)
{
    ...
}
// There is no C++ equivalent to the exception 'finally' clause:
//finally
{
    ...
}

C++ doesn't have extension methods, so a VB.NET extension method is just converted to an ordinary C++ static method (calls to the method have to be adjusted to static calls using the class name).

VB.NET C++
Public Module ContainsExtension
    <System.Runtime.CompilerServices.Extension> _
    Public Sub ExtensionMethod(ByVal myParam As String)
        ' ...
    End Sub
End Module
Class TestClass
    Private Sub TestMethod()
        Dim s As String = "test"
        s.ExtensionMethod()
    End Sub
End Class
#include <string>

class ContainsExtension final
{
public:
    static void ExtensionMethod(const std::string &myParam)
    {
        // ...
    }
};
class TestClass
{
private:
    void TestMethod()
    {
        std::string s = "test";
        ContainsExtension::ExtensionMethod(s);
    }
};
C++ VB.NET
for (std::string s : StringList)
{
    ...
}
For Each s As String In StringList
    ...
Next s

VB generics and C++ templates are implemented in totally different ways — VB generics is a runtime feature, while C++ templates result in separate classes created at compile-time, but you can still often achieve the same result by converting one to the other.

Creating a List

VB.NET C++
Dim myVar As New List(Of Integer) std::vector<int> myVar;

Creating a Dictionary

VB.NET C++
Dim myVar As New Dictionary(Of String, Integer) std::unordered_map<std::string, int> myVar;

Defining a Generic Class

VB.NET C++
Public Class GenericClass (Of T)
End Class
template<typename T>
class GenericClass
{
};

Defining a Generic Class with a Constraint

VB.NET C++
Public Class GenericClass (Of T As SomeBase)
End Class
#include <type_traits>

template<typename T>
class GenericClass
{
    static_assert(std::is_base_of<SomeBase, T>::value, "T must inherit from SomeBase");
};

Defining a Generic Class with a 'new' Constraint

VB.NET C++
Public Class GenericClass (Of T As New)
End Class
#include <type_traits>

template<typename T>
class GenericClass
{
    static_assert(std::is_default_constructible<T>::value, "T requires default-constructible elements");
};

Defining a Generic Method

VB.NET C++
Public Function Compare(Of T)(param1 As T, param2 As T) As Integer public:
template<typename T>
int Compare(T param1, T param2)

Defining a Generic Method with a Constraint

VB.NET C++
Public Sub Swap(Of T As Class)(ByRef l As T, ByRef r As T) #include <type_traits>

public:
template<typename T>
void Swap(T &l, T &r)
{
    static_assert(std::is_class<T>::value, "T must be a class");
}
VB.NET C++
Imports Foo
Imports Foo.Bar  ' 'Bar' is a type

' namespace alias:
Imports foo = SomeNamespace
' type alias:
Imports bar = SomeNamespace.SomeType
using namespace Foo;
*no equivalent*

// namespace alias:
namespace foo = SomeNamespace;
// type alias:
using bar = SomeNamespace.SomeType;
C++ VB.NET
public:
int &operator [](int index)
{
    return field[index];
}

*for a read-only indexer, return an int instead of an int reference (remove the '&').
Default Public Property Item(ByVal index As Integer) As Integer
    Get
        Return field(index)
    End Get
    Set
        field(index) = Value
    End Set
End Property
C++ VB.NET
class DerivedClass : public BaseClass
{
public:
    virtual void MethodOverrideOne() override
    {
    }
    virtual void MethodOverrideTwo() final override
    {
    }
};
Public Class DerivedClass
    Inherits BaseClass

    Public Overrides Sub MethodOverrideOne()
    End Sub
    Public Overrides NotOverridable Sub MethodOverrideTwo()
    End Sub
End Class

C++ doesn't have a separate 'interface' concept, but this is done just as easily in C++ using a class with only 'pure virtual methods'.

VB.NET C++
Public Interface IFoo
    Sub Method()
End Interface
class IFoo
{
public:
    // pure virtual method:
    virtual void Method() = 0;
};
VB.NET C++
myVar = Function(text As String) text.Length myVar = [&] (const std::string &text)
{
    return text.length();
};

For Loop

VB.NET C++
For i As Integer = 1 To 9
Next i
for (int i = 1; i <= 9; i++)
{
}

For Each Loop

VB.NET C++
For Each s As String In StringList
Next S
for (std::string s : StringList)
{
}

While Loop

VB.NET C++
Do While condition
Loop

or:

While condition
End While
while (condition)
{
}

Do While Loop

VB.NET C++
Do
Loop While condition
do
{
} while (condition);

Loop Until

VB.NET C++ (no specific 'loop until' construct)
Do
Loop Until condition
do
{
} while ( ! condition);

Do Until

VB.NET C++ (no specific 'do until' construct)
Do Until condition
Loop
while ( ! condition)
{
}
VB.NET C++
Public Module Utility
    Public Sub UtilityMethod()
        ...
    End Sub
End Module

or:

Public NotInheritable Class Utility
    Private Sub New() ' prevent instantiation
    End Sub

    Public Shared Sub UtilityMethod()
        ...
    End Sub
End Class
class Utility final
{
public:
    static void UtilityMethod()
    {
        ...
    }
};
VB.NET C++
Dim s As String = "multiline
    string"
std::string s = R"(multiline
    string)";
VB.NET C++
Public MustInherit Class AbstractClass
    Protected MustOverride Sub AbstractMethod()
End Class
class AbstractClass
{
protected:
    virtual void AbstractMethod() = 0;
};

In C++17, the std::any type offers a good equivalent to System.Object.

VB C++ (C++17)
Dim o As Object = 1
Dim i As Integer = DirectCast(o, Integer)
Dim t As Type = o.GetType()
#include <any>
#include <typeinfo>

std::any o = 1;
int i = std::any_cast<int>(o);
std::type_info t = o.type();

VB.NET operator overloading is similar to C++ operator overloading, except that VB.NET operator overloads are static methods while C++ operator overloads are instance methods.

C++ VB.NET
class SomeType
{
private:
    int IntValue = 0;

public:
    int operator + (const SomeType &Y)
    {
        return this->IntValue + Y.IntValue;
    }
};
Public Class SomeType
    Private IntValue As Integer = 0

    Public Shared Operator + (ByVal impliedObject As SomeType, ByVal Y As SomeType) As Integer
        Return impliedObject.IntValue + Y.IntValue
    End Operator
End Class
VB.NET C++
+, -, *, >, >=, <, <=, <<, >>
&    (string concatenation)
()    (indexing)
And
Or
AndAlso
OrElse
Not
Xor
Mod
x ^ y
=
Is
IsNot
<>

If(x, y, z)
If(x, y)

x / y    (where x and y are integers)
x / y    (where x and y are doubles)
x \ y    (where x and y are integers)

x \ y    (where x and y are doubles)
unchanged
+    (string concatenation)
[]
&
|
&&
||
! or ~    (depending on context)
^
%
std::pow(x, y)    (no exponentiation operator)
= or ==    (depending on context)
==
!=
!=

x ? y : z
x != nullptr ? x : y

x / static_cast<double>(y);
x / y
x / y

In C++, it is more common to call them 'default parameters'.

C++ VB.NET
void TestOptional(int x = 0)
{
    ...
}
Private Sub TestOptional(Optional ByVal x As Integer = 0)
    ...
End Sub
C++ VB.NET

Raw pointers:

Foo *f1 = new Foo();

Smart pointers:

std::shared_ptr<Foo> f2 = std::make_shared<Foo>();
Dim f1 As New Foo()

Dim f2 As New Foo()

C++ does not have properties, so you must use get/set methods instead:

VB.NET C++
Public Property IntProperty() As Integer
    Get
        Return intField
    End Get
    Set(ByVal value As Integer)
        intField = value
    End Set
End Property
public:
int getIntProperty() const
{
    return intField;
}
void setIntProperty(int value)
{
    intField = value;
}

For simple cases, VB's Select construct can be converted to the C++ switch construct. However, if any of the Case statements include range or non-constant expressions, then the equivalent is an if/else block.

VB C++
' converts to switch:
Select Case x
    Case 0
        ...
    Case 1
        ...
End Select

' converts to if/else:
Select Case x
    Case 1 To 3
        ...
    Case Is < 10, Is > 20, Is = 15
        ...
End Select
// converts to switch:
switch (x)
{
    case 0:
        // ...
        break;
    case 1:
        // ...
        break;
}

// converts to if/else:
if (x >= 1 && x <= 3)
{
    ...
}
else if ((x < 10) || (x > 20) || (x == 15))
{
    ...
}

The C++ equivalent to a VB.NET shared constructor uses a private nested class.

VB.NET C++
Class Foo
    Public Shared field As Integer

    Shared Sub New()
        field = 1
    End Sub
End Class
class Foo
{
public:
    static inline int field = 0;

private:
    class StaticConstructor
    {
    public:
        StaticConstructor()
        {
            field = 1;
        }
    };

private:
    static inline Foo::StaticConstructor staticConstructor;
};
VB.NET C++
SyncLock x
    ...
End SyncLock
#include <mutex>

...

{
    std::scoped_lock<std::mutex> lock(x);
    ......
}

There is no direct equivalent in C++ to the VB 'TypeOf' operator, but you can replicate the behavior by testing the result of a 'dynamic_cast':

VB.NET C++
Dim b As Boolean = TypeOf f Is Foo bool b = dynamic_cast<Foo*>(f) != nullptr;

C++ 'typeid' is only equivalent to VB 'GetType' for template type parameters:

VB.NET C++
Private Sub method(Of T)()
    Dim x As Type = GetType(T)
End Sub
template<typename T>
void method()
{
    std::type_info t = typeid(T);
}
VB.NET C++
Using f As New Foo()
    f.method()
End Using
{
    Foo *f = new Foo();
    f->method();
    delete f;
}

or, if 'Foo' is designed for RAII:

{
    Foo f;
    f.method();
}
VB.NET C++ (omitting null handling)
Left(x, 2)
Right(x, 2)
Mid(x, 3)
InStr(x, y)
InStrRev(x, y)
x.substr(0, 2)
x.substr(x.length() - 2)
x.substr(2)
x.find(y) + 1
x.rfind(y) + 1

These are rarely used, but still supported.

VB.NET C++
Dim myIntegerVar%
Dim myStringVar$
Dim myFloatVar!
Dim myDoubleVar#
int myIntegerVar = 0;
std::string myStringVar = "";
float myFloatVar = 0;
double myDoubleVar = 0;

Copyright © 2004 – 2024 Tangible Software Solutions, Inc.