Using the "point" is a way of subdividing a larger category into a smaller one. For example, it should be easy to decipher
Many books use dashes to indicate subsections of a chapter, but other books use decimal points (including Stewart's Calculus, and Savitch's C++).
The concept of being able to subdivide something into component parts (each part having a different name and perhaps a different data type) is the underlying basis for what are, in general, called "RECORD variables." Since such a variable has many independent subsections, it is often called an aggregate data type.
Many contemporary programming languages allow users to "subdivide" variables, or (looking at it in another way) to unite different variables (with possibly different data types) under one name. A variable with multiple subsections is said to be of a record (e.g., Pascal), structure (C), or derived (Fortran-90) type. Each of the subsections of a record variable is called a field or component.
C++ has built upon the constructs used in C for such record variables. In C such a record variable was called a structure and used the keyword struct. C++ allows the use of this same keyword but has "improved" upon its basic concept by permitting the inclusion not only of variables but also functions as component parts of the record variable and also introducing the concepts of private and public attributes (or modes). (These keywords may be used as section delimiters within a struct.)
One of the concerns of contemporary programming is that of "data encapsulation," that is, somehow protecting data and operations on data from misuse. The attributes of public and private regulate which sections of a record variable are accessible to programmers in general and which are not. Those designated private are accessible only from functions within the record variable. Those designated public are accessible from any function/procedure according to standard rules (i.e., by using a variable declared of that record type).
C++ has created a new alternative to the struct (record) variable of C and it is called a class. The difference is that (in C++), by default, all member functions and variables in a struct are public. On the other hand, in a class all member functions and variables are private. In both a struct and a class one can override the default attribute of components by explicitly stating which variables and functions are private and which are public.
A C++ (C) struct or class is basically only a blueprint or template of a definition of a new data-type. Variables of that type do not exist unless explicitly declared. In the vocabulary used by "object-oriented programming," a class frequently refers to the template of a record-type structure that includes both "member variables" and "member functions." When specific identifiers are actually declared to be of a specific class, those identifiers are called objects (from which comes the term "object-oriented programming"). Sometimes books use the term instantiation to refer to the creation of an "instance" of a specific variable of a given class type.
Technically, in C++, a struct is also a class since C++ permits a struct to contain member functions. However, to avoid all confusion, most beginning C++ books merely ignore the struct keyword and only use class. That should be the custom for programs written in this course. On the other hand, one should realize that, technically, a struct is merely a class in which member variables and functions are, by default, public, especially when looking at older C programs in texts or references.
It is also possible to define a type and declare variables of that same time together in one statement, but that style is frowned upon and can cause confusion.
One defines a new type in this way: begin with the keyword class (or struct), then give an identifier which will be the name of the class. The identifier is followed by an opening brace which begins the declaration of subsections of the structured type. For our purposes, two keywords should mark the two major sections: public: and private: (one can omit the appropriate word if there will be no fields/components having that attribute or if one wishes to use the default attribute).
This is followed by a closing brace and a semicolon (one of the few times a semi-colon is necessary after a closing brace). It is permitted actually to list identifiers between the closing brace and the semi-colon, thereby declaring the identifiers in this way, but this style is not recommended.
NOTE: Such definitions of classes (and structs) should be included in the program code after the #include statements and before any function code or prototype lines.
As an example, let us first define a structured variable type that will not contain any internal functions, and all of whose components are public.
class INFOLINE
{
public:
char name[30];
char address[50];
int zip;
int accntnum;
};
NOTES:
E.g.
INFOLINE account, list[100], temp;The definition of INFOLINE sets up a "blueprint" for how each variable declared (i.e., how account, how each of the 100 elements of the array list, and how temp) is structured in memory. To turn the definition above into a picture, the definition of the class INFOLINE means that the C++ program understands that each variable declared to be of the new datatype INFOLINE has this structure:
name address zip accntnum | | \ / v v v v ____________________________________________ | | | ... | | | | ... | | | | | |_|_|_____________|_|_|_|___________|_|_|_|_| 0 1 29 0 1 48 49Here we can visualize the 82 contiguous memory locations, the first 30 of which comprise the name component of a variable of type INFOLINE, the next 50 comprising the address component, the next one corresponding to the zip component, and the final space corresponding to accntnum.
To reference a field (or component) of the variable account (declared above), we use the "dot" (or "point") notation (as in Star Trek). If the field referenced is a collection of variables (as in the case where it might be an array), we can use other means to identify individual variables (e.g., subscripts).
E.g.
account.name[1] account.address[2] account.zip account.accntnumIf each element in array is a record variable, we must identify the array item first, and then its subsections (i.e., fields). For example, list was declared to be an array of INFOLINE-type variables, which is a record type. Thus, list[45] is one record variable in the array. The zip field of this one variable is indicated:
I - We can have assignments of "entire" record variables to other record variables,
E.g.
temp = list[i](This assignment actually copies the values of 82 memory locations, since that is how many variables comprise one record variable of type INFOLINE!)
II - We can have assignments of (sub-)sections of a record variable. This is the more commonplace practice.
E.g.
cin >> newzip; list[j].zip = newzip; ... tempzip = list[j].zip; cout << tempzip << endl;
One "inherits" attributes from a defined, "base" class (or struct) by mentioning the name of the class between the header of the new, "derived" class and the opening brace which encloses the components of that "derived" class.
For example, suppose we define a "base" class describing a two-dimensional geometrical object. We could do this as follows:
class twod
{
public:
float length, width;
};
Thus, variables declared to be of type twod would have
two components or fields, one named length and the other
named width.
One could then theoretically think of a three-dimensional geometrical object as sharing with a two-dimensional object the two basic dimensions and adding a third. We could describe this by explicitly defining a new (derived) data type and declaring it to inherit part of its attributes from the base data type.
In this case, we could define the new data type as follows:
class threed
: public twod
{
public:
float height;
};
Notice that after the header class threed which defines
the name of the new, derived class, we include a colon,
the keyword public and the name of the base class,
in this case twod.
This definition means that the derived class, threed has access to everything in twod that was declared to be public, and, in addition, it has its own public component, called height.
With such definitions of the classes twod and threed, the following is a legitimate main program:
int main()
{
// declarations of class variables
twod rectangle,square;
threed box;
// declaration of other variables
float volume,area;
// assignment of values to variable components
rectangle.length = 3;
rectangle.width = 4;
// box inherits the components of
// length and width from the class twod
// and thus can make use of them.
box.length = 4;
box.width = 5;
// box also has its own component
// of height from its threed class def.
box.height = 6;
area = rectangle.length * rectangle.width;
volume = box.length * box.width * box.height;
// output of computations
cout << "area of the rectangle = " << area << endl;
cout << "volume of the box = " << volume << endl;
cout << endl << "that's all folks!" << endl;
return 0;
}
One of the key differences between object-oriented programming languages and older languages is the ability to join data with appropriate functions together in some sort of "encapsulation." Although Pascal and C made record/structured variables very common, C++ and Java have made the use of member functions commonplace.
This page is maintained by Dennis C. Smolarski, S.J.
dsmolarski@math.scu.edu
© Copyright 1997, 1998, 2000 Dennis C. Smolarski, SJ, All rights reserved.
Last changed: 1 November 2000.