C++ Lecture 2
[Previous Lecture]
[Lecture Index]
[Next Lecture]
Intro to C++ Classes
- a class is an `enhanced' structure
- like a C structure, it has data fields;
also called
- instance variables
- data members
- member variables
(instance means an actual copy of a class)
- can specify `functions' that manipulate the class
These `functions' are referred to as:
- methods
- instance methods
- member functions
- access to instance variables & methods can be restricted
Instance Methods
Access Control
- public:
- allows things outside the class to access the following entities
- private:
- prevents things outside the class from accessing the following entities
- class xyz
- starts in `private mode'
- struct xyz
- starts in `public mode'
class Xyz {
int a; // private by default
public:
int b;
int foo() {
return a + b + c + bar();
}
private:
int c;
int bar() { return a * b * c; }
};
int
test()
{
Xyz x;
return x.b + x.foo() // ok
+ x.a // NOT allowed
+ x.c // NOT allowed
+ x.bar(); // NOT allowed
}
Creating Header Files
Header files typically contain:
-
symbolic constants
-
type definitions
-
function prototypes
-
global variable declarations
General form of header file:
#ifndef FILENAME_H
# define FILENAME_H
// Declaration of simple types
// Definition of symbolic constants
// Forward declaration of classes
# include "others.h"
// Definition of classes
// Global variables
// Function prototypes
#endif /* FILENAME_H */
Goal is to avoid problems caused by multiple inclusions,
and to deal with circular dependencies.
grow-3.h
#ifndef GROW_H
# define GROW_H
class Growing_buffer {
enum { INITIAL_SIZE = 16 };
char *buf;
int n_used;
int size;
public:
// Default constructor
Growing_buffer();
// Specifies initial size of buffer
Growing_buffer(int isize);
// Specifies initial contents of buffer
Growing_buffer(const char *str);
// Add a character to the buffer
void addc(char c);
// Empty the buffer
void reset();
// Return buffer length
int getlen() const { return n_used; }
// Return buffer contents
const char * getbuf() const { return buf; }
~Growing_buffer();
};
#endif /* GROW_H */
grow-3.cc
#include <string.h>
#include "grow-3.h"
Growing_buffer::Growing_buffer()
{
size = INITIAL_SIZE;
n_used = 0;
buf = new char[size];
}
Growing_buffer::Growing_buffer(int isize)
{
size = isize;
n_used = 0;
buf = new char[size];
}
Growing_buffer::Growing_buffer(const char *str)
{
size = strlen(str) + 1;
n_used = size;
buf = new char[size];
strcpy(buf, str);
}
void
Growing_buffer::addc(char c)
{
if (n_used >= size) {
char *nbuf;
size *= 2;
nbuf = new char[size];
memcpy(nbuf, buf, size / 2);
delete [] buf;
buf = nbuf;
}
buf[n_used++] = c;
}
void
Growing_buffer::reset()
{
n_used = 0;
}
Growing_buffer::~Growing_buffer()
{
delete [] buf;
}
grow-3-main.cc
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "grow-3.h"
int
readline(FILE *fp, Growing_buffer *gb)
{
int c;
gb->reset();
while ((c = fgetc(fp)) != EOF) {
gb->addc(c);
if (c == '\n')
break;
}
gb->addc('\0');
return gb->getlen() - 1;
}
int
main(int argc, char **argv)
{
int i;
int lineno;
int ecode = 0;
FILE *fp;
Growing_buffer gbuf;
for (i = 1; i < argc; i++) {
fp = fopen(argv[i], "r");
if (!fp) {
fprintf(stderr, "can't open %s - %s\n",
argv[i], strerror(errno));
ecode = 1;
continue;
}
lineno = 1;
while (readline(fp, &gbuf) > 0) {
printf("%d %s", lineno, gbuf.getbuf());
lineno++;
}
fclose(fp);
}
return ecode;
}
Some Differences from C
Stream Input
- #include <iostream.h>
-
- cin
-
global variable associated with standard input
- >>
-
handles input of most types (char, int,
double, etc.)
Skips any white space before reading
- get(char &)
-
read a character - does not skip white space
- get(char *, int size, char delim = '\n')
-
read up to the delimiter character - does not skip white space
does not read the delimiter
- read(void *, int size)
-
used to read arbitrary data (such as structures, etc.,
equivalent to fread()).
- peek()
-
like get(char &), but doesn't consume the
character
- fail()
-
test if last operation failed
int i;
float f;
char c;
char buf[1024];
cin >> i;
cin >> f;
cin >> c;
cin.get(c);
c = cin.peek();
cin.get(buf, sizeof(buf), '\n');
if (cin.fail()) { // or if (!cin) {
cerr << "Couldn't read buffer\n";
exit(1);
}
Stream Output
- cout, cerr
-
global variables associated with standard output and standard error
- <<
-
handles output of most types (char, int,
double, etc.)
- put(char &)
-
write a character
- write(char *str, int n)
-
write a n characters
- flush()
-
flush any buffered output (e.g.,
actually write to the file)
- fail()
-
test if last operation failed
int i;
cout << "Processing output";
for (i = 0; i < 8291; i++) {
// a slow function
process_data(i);
cout << '.';
cout.flush();
}
cout << "done\n";
char *s = "hi there folks";
// print whole string
cout << s;
// print first n characters
cout.write(s, 8);
if (!cout)
cerr << "problem writing to output\n";
References
- new `kind' of variable
- variable is declared as a reference by using an &
- references must be initialized
- references can't be null
- simply hides use of pointers (syntactic sugar):
- when a reference is initialized to something,
the address of something is saved.
- when a reference is used, the contents of the address is used
/* References */ /* Pointers */
int i = 10; int i = 10;
int &iref = i; int *iref = &i;
/* this changes i */ /* this changes i */
iref = -3; *iref = -3;
printf("%d\n", i); printf("%d\n", i);
- most commonly used as parameter type:
- avoids copying structures
- allows function to modify caller's value
(like var parameters in modula-2/pascal)
Examples:
double
Point::distanceTo(const Point &p) const
{
double dx = x - p.getX();
double dx = y - p.getY();
return sqrt(dx * dx + dy * dy);
}
/* ... */
int
main()
{
Point a(2, -6), b(4, 9);
double d = a.distanceTo(b);
/* ... */
}
void
halfIt(Point &p)
{
p.move(-p.getX() / 2, -p.getY() / 2);
}
- can also be used in the return type of a function
Useful to
- allow operations to be chained
- provide (possibly const) access to
a instance variable
Note: never return a refernce to a local variable.
Point &
minPoint(Point &p1, Point &p2)
{
Point zero(0, 0);
if (zero.distanceTo(p1)
< zero.distanceTo(p2))
return p1;
else
return p2;
}
int
main()
{
Point a(3,4), b(5, 2);
/* ... */
minPoint(a, b).move(0, -1);
/* ... */
}
[Previous Lecture]
[Lecture Index]
[Next Lecture]