class Array {
public:
Array() : len(0) { data = NULL; }
Array(int size) : len(size) { data = new int[len]; }
Array(const Array & a) : len(a.len) {
data = new int[len];
for (int i = 0; i < len; ++i) data[i] = a.data[i];
}
int length() const { return len; }
// Array element access - lvalue and rvalue
virtual int & operator [] (int i) {
static int bucket;
return (i >= 0 && i < len) ? data[i] : bucket;
}
virtual int operator [] (int i) const {
return (i >= 0 && i < len) ? data[i] : 0;
}
// Assignment (sizes need not match)
Array & operator = (const Array & a) {
delete [] data; data = new int[len = a.len];
for (int i = 0; i < len; ++i) data[i] = a.data[i];
return *this;
}
// Utility for printing
virtual void print(ostream & o) {
o << "[";
for (int i = 0; i < length(); ++i)
o << (i == 0 ? "" : " ") << data[i];
o << "]";
}
private:
int *data; // The values in the array
int len; // The size of the array
};
inline
ostream & operator << (ostream & o, const Array & a) {
a.print(o);
return o;
}
Errors:
int * (*x)(int *); int i;
Constructors are called begining with the earliest ancestor class' constructor, down the inheritance hierarchy to the last derived class' constructor. Destructors are called in the reverse order, beginning with the last derived class' destructor.
If the base class destructor is not virtual, and we have a pointer to a base that is actually the address of a derived object, only the destructor for the base will be called, leaving the work of the derived destructor undone.
Friends of class A are classes or functions that enjoy the same access privileges as member functions of class A. That is, they can access the private data and methods of class A. The specification of friendship is part of the interface definition of class A, so is a privilege extended by class A itself.
If copy constructors or assignment is not defined, then the default
action is memberwise copy construction or assignment of the data fields.
This means that the copy constructors or assignment operators for the types
of those fields are used. This behavior is applied recursively.
The same behavior occurs for inheritance hierarchies - the copy constructor
and/or assignment of the base class are used. Even if they are defined
in the derived object, these operations are still used for the base part
of the class.
CC = CC all: hello hello: hello1.o hello2.o $(CC) -o hello hello1.o hello2.o hello1.o hello2.o: hello.h hello1.o: hello1.c $(CC) -c hello1.c hello2.o: hello2.c $(CC) -c hello2.c
class Array {
public:
Array(int size) : len(size) { data = new int[len]; }
Array(const Array & a) : len(a.len) {
data = new int[len];
for (int i = 0; i < len; ++i) data[i] = a.data[i];
}
virtual ~Array() { delete [] data; }
int length() const { return len; }
// Array element access
virtual int & operator [] (int i) {
if (i < 0 || i >= len) throw Error("index out of bounds");
return data[i];
}
// Assignment (sizes need not match)
Array & operator = (const Array & a) {
if (this == &a) return *this;
delete [] data; data = new int[len = a.len];
for (int i = 0; i < len; ++i) data[i] = a.data[i];
return *this;
}
// Utility for printing
virtual void print(ostream & o) const {
o << "[";
for (int i = 0; i < length(); ++i)
o << (i == 0 ? "" : " ") << data[i];
o << "]";
}
class Error {
public:
const char * const emessage;
Error(const char * m = "") : emessage(m) { }
};
private:
int *data; // The values in the array
int len; // The size of the array
};
inline
ostream & operator << (ostream & o, const Array & a) {
a.print(o);
return o;
}
And suppose you have the growable array derived from Array:
class GrowableArray : public Array {
public:
GrowableArray(int size) : Array(size) { fill(); }
private:
// Grow the array and copy values
void grow() {
. . .
}
};
You can assume that the method grow increases the array
size by some amount.
Show the code you would add to the class so that an out of range
exception would not occur, but the array would grow to be the necessary size.
Add the following implementation of int & operator [] (int) to GrowableArray:
int & GrowableArray::operator [] (int i) {
while(true) {
try {
return Array::operator[] (i);
}
catch (...) {
if (i < 0) throw Error("negative index");
grow();
continue;
}
}
}