Definition: An abstract data type (ADT) is an encapsulation of data and operations on the data.
Note: In spite of its name, an ADT is an extremely powerful and very concrete programming tool. Solutions to large programming problems are typically designed and constructed using cooperating instances of ADTs.

In both Java and C++, the class is the primary implementation mechanism for ADTs. While there are a few syntactical differences, the basic definition, implementation, and use of classes is very similar in the two languages. Consider the following simple example (ignore for now the use of "->" versus "." in various places in the C++ version):

JavaC++
public class Complex
{

    private double realPart, imaginaryPart;


    public Complex()
    {
        this.realPart = 0.0;
        this.imaginaryPart = 0.0;
    }
    public Complex(double re, double im)
    {
        this.realPart = re;
        this.imaginaryPart = im;
    }
    
    public Complex add(Complex rhs)
    {
        return new Complex(this.realPart+rhs.realPart,
                this.imaginaryPart+rhs.imaginaryPart);
    }

    public double length()
    {
    	return Math.sqrt(realPart*realPart +
        	imaginaryPart*imaginaryPart);
    }
}
class Complex
{
private:
    double realPart, imaginaryPart;

public:
    Complex()
    {
        this->realPart = 0.0;
        this->imaginaryPart = 0.0;
    }
    Complex(double re, double im)
    {
        this->realPart = re;
        this->imaginaryPart = im;
    }
    
    Complex add(Complex rhs)
    {
        return Complex(this->realPart+rhs.realPart,
             this->imaginaryPart+rhs.imaginaryPart);
    }
    
    double length()
    {
    	return sqrt(realPart*realPart +
        	imaginaryPart*imaginaryPart);
    }
};

The previous C++ example was constructed to look as similar as possible to the Java version. While perfectly valid, it is more conventional to split the definition and implementation of C++ classes into two files (see also Separate compilation). Hence the following is more representative of a typical C++ implementation:

Complex.hComplex.c++
class Complex
{
private:
    double realPart, imaginaryPart;

public:
    Complex();
    Complex(double re, double im);
    Complex add(Complex rhs);
    double length();
};
#include "Complex.h"

Complex::Complex() : realPart(0.0), imaginaryPart(0.0)
{
}
Complex::Complex(double re, double im) : realPart(re), imaginaryPart(im)
{
}
Complex Complex::add(Complex rhs)
{
    return Complex(this->realPart+rhs.realPart,
        this->imaginaryPart+rhs.imaginaryPart);
}
double Complex::length()
{
    return sqrt(realPart*realPart +
        imaginaryPart*imaginaryPart);
}

The C++ struct

Largely for historical reasons, C++ also has something called "struct". A struct is exactly the same as a class except for default accessibility of identifiers. That is, identifiers default to private in a class, but default to public in a struct. Hence vbl is private in MyClass, but it will be public in MyStruct:

class MyClass
{
    float vbl;
    …
};
struct MyStruct
{
    float vbl;
    …
};

A typical convention (and the one we will follow) is to use class for ADTs and to use struct when simply packaging data elements with little or no code.

An annoying syntactical observation: Do not neglect the semicolon (;) at the end of C++ class and struct definitions!

Special Methods in C++ Classes

You will recall constructors in Java classes. C++ classes have constructors as well, and they serve exactly the same purpose – namely to allow you to be sure that all created class instances are properly initialized. There were two constructors in both the Java and C+ versions of class Complex above.

What is different in C++ is that there are two "special" constructors: the copy constructor and the no-parameter constructor. (The latter is sometimes called the "default constructor".) In addition, C++ has an additional "special method" called the destructor. We will learn why copy constructors and destructors are important in the Memory management section. We will see examples illustrating why the no-parameter constructor is "special" in the Stack-allocated objects and Stack-allocated arrays sections.

Usage

Instances of class Complex can be created and used in a similar manner in the two languages:

Java C++: Version 1 of client C++: Version 2 of client
void client()
{
    Complex c1 = new Complex(1.8, -3.1);
    Complex c2 = new Complex(-1.1, 9.8);
    Complex c3 = c1.add(c2);
    …
}
void client()
{
    Complex* c1 = new Complex(1.8, -3.1);
    Complex* c2 = new Complex(-1.1, 9.8);
    Complex c3 = c1->add(c2);
    …
}
void client()
{
    Complex c1(1.8, -3.1);
    Complex c2(-1.1, 9.8);
    Complex c3 = c1.add(c2);
    …
}

What's up with the two different C++ versions? And what's the deal with the asterisk (*) and arrow (->) in Version 1? Let's not worry about asterisks and arrows for now (they will be explained in the Basic Pointer Use and Memory management sections), but as for the two different C++ versions, see Stack-allocated objects next.