0% found this document useful (0 votes)
39 views33 pages

Lec08 (Topic 4 Define Classes)

The document discusses constructors and destructors in C++ classes. It defines constructors as special methods that initialize object attributes when an instance is created. There are three types of constructors: default, overloaded, and copy. Constructors have the same name as the class and are automatically called during object creation. Destructors are special methods that perform cleanup when an object is destroyed. They have the same name as the class preceded by a tilde.

Uploaded by

huaiencheeng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views33 pages

Lec08 (Topic 4 Define Classes)

The document discusses constructors and destructors in C++ classes. It defines constructors as special methods that initialize object attributes when an instance is created. There are three types of constructors: default, overloaded, and copy. Constructors have the same name as the class and are automatically called during object creation. Destructors are special methods that perform cleanup when an object is destroyed. They have the same name as the class preceded by a tilde.

Uploaded by

huaiencheeng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 33

LECTURE 8

Defining Classes (Part 2)


Constructors
• A constructor is a special type of method that is used to perform initialization
of object/instance attributes (data members).

• Whenever an instance of a class is created, a constructor is called


automatically.

• Constructors cannot be explicitly called. They are invoked automatically


whenever an instance is created.

• Constructor has no return value (not even void).

• 3 types of constructors: default, overloaded, copy.

• A class can have more than one constructor.


Constructors
• Constructors always have the same name as the class name.

• Since there is no return value, we declare a constructor like any other


method, but omit a return type.

class Student {
public:
Student(); // Default constructor
Student(int id); // Overloaded constructor
Student(string name); // Overloaded constructor
Student(const Student& existingStudent); // Copy constructor

};

Same name as class name


Default Constructors
• Default constructor is the constructor that is called when no
arguments are provided in the instance declaration (constructor with
no argument/parameter).

• A class can have only one default constructor.

• We use default constructor to set attributes to initial/default values


when no argument is not provided during object creation.

class Student {
int idNum;
public:
Student() { // default constructor
idNum = 0; // set default value
}
};
int main() {
Student s1; // call default constructor
Student *ps = new Student; // call default constructor
Default Constructors
If you do not provide a default constructor, C++ automatically creates an
empty one (no implementation)

// Your code
class Student { // no default constructor is provided
};

// Compiler code
class Student {
public:
Student() { // compiler's default constructor
// no definition/implementation
}
};
Example: Default Constructor
class Student {
int idNum;
public:
Student() { // default constructor
idNum = 0; // set default value
cout << "A Student object is created!\n";
}
void setIDNum (int id) { Output:
idNum = id;
} A Student object is created!
int getIDNum() { Student id is 0
return idNum; Student id is 123
}
};
int main() {
Student s1; // call default constructor
cout << "Student id = "
<< s1.getIDNum() << endl;
s1.setIDNum (123);
cout << "Student id = "
<< s1.getIDNum() << endl;
return 0;
}
Overloaded Constructors
• Overloaded constructors are constructors that have parameter(s).
• We could provide arguments when creating an instance of a class,
thus invoking an overloaded constructor.
• Overloaded constructors are used to initialize attributes to values
passed as arguments.

class Student {
int idNum;
public:
Student (int id) { // overloaded constructor (1 parameter)
idNum = id; // assign parameter value to attribute
}
};
int main() {
Student s1 (123); // call overloaded constructor
Student *ps = new Student (234); // call overloaded constructor
Overloaded Constructors
• We may provide default arguments for constructor parameters.
• We must follow the same rules as when overloading regular
functions (i.e. parameter lists must differ)

class Student {
int idNum;
public:
Student (int id = 0) { // 2-in-1: alternate default constructor,
// overloaded constructor
idNum = id;
}
};
int main() {
Student s1; // call alternate default constructor
Student *ps = new Student (234); // call overloaded constructor
Constructor Initializer List
• Constructor initializer list allows us to initialize attributes before constructor
body is executed.

• Is particularly important when initializing const attributes.

• Is placed after the constructor parameter list but before constructor body.

• A single colon (‘:’) is used to separate the parameter list from the initialize list

Student::Student (<parameter list>) : <initializer list> { ... }

Constructor name Colon Constructor body

Initializer list Initializer list


Constructor Initializer List
The constructor initializer list has the following format:
Student::Student (param1, param2)
: attribute1 (param1), attribute2 (param2)
{ ... }

The parameter list can be empty.

// Initialize 1 attribute without parameter


class Student {
int idNum;
public:
Student () // 0 parameter
: idNum (0) // initialize idNum to 0
{ } // constructor body
};
Constructor Initializer List
// Initialize 1 attribute through 1 parameter
class Student {
int idNum;
public:
Student (int id = 0) // 1 parameter
: idNum (id) // initialize idNum to the value of id
{ } // constructor body
};

// Initialize 2 attributes through 2 parameters


class Student {
int idNum;
string name;
public:
Student (int id, string name) // 2 parameters
: idNum (id), name (name) // "this" pointer is not required
{ } // constructor body
};
int main() {
Student s1 (123, "Michael");
Copy Constructors
• Copy constructor initializes an new object by copying the value of
attributes from an existing object of the same class.
• Copy constructor is invoked when an instance is created with either of
the following structures:
Student x; // Invokes default constructor
Student y = x; // Invokes copy constructor with x
Student z ( y ); // Invokes copy constructor with y

• C++ provides a default copy constructor if you do not declare one. It


simply copies the value of attributes into the new instance. This type of
copy is called shallow copy.
Copy Constructors
• Usually you do not have to provide a copy constructor, unless you
want to perform additional initialization that is not provided by default
copy constructor (for example, deep copy a pointer attribute).

• Copy constructor must have the following method interface

Parameter is of the
same type as the class

Student (const Student& existingInstance);

const ensures that the existing


instance will not be altered by Pass by Parameter name refers to the
the copy constructor reference instance that is being “copied”
Example: Copy Constructor
const int SIZE = 3; int main() {
class Student { int marks[] = {97,98,99};
public: Student s1 (marks);
Student (int* themarks); // overloaded Student s2 (s1);
Student (const Student& st); // copy constructor Student s3 = s2;
void print(); s1.print();
private: s2.print();
int* marks; // dynamic attribute s3.print();
}; return 0;
Student::Student (int* themarks) { }
marks = new int[SIZE];
for (int i = 0; i < SIZE; i++)
marks[i] = themarks[i];
}
Student::Student (const Student& st) {
marks = new int[SIZE]; // create dynamic array
for (int i = 0; i < SIZE; i++) Output:
marks[i] = st.marks[i]; // copy array
} Marks = 97 98 99
void Student::print() { Marks = 97 98 99
cout << "Marks = "; Marks = 97 98 99
for (int i = 0; i < SIZE; i++)
cout << marks[i] << " ";
cout << endl;
}
Destructor
•A destructor is a special type of method that is invoked whenever an instance is
destroyed (de-allocating an instance).

•Destructors are automatically called when an automatically allocated instance


goes out of scope, or when a dynamically allocated instance is explicitly deleted
(using delete operator).

•Destructors have no return value and no parameter.

•There is only one destructor for each class.

•Destructor has the same name as the class, except that it is preceded by a tilde
‘~’.
class Student {
public:
~Student();
};
Destructor
Destructors are generally used to perform any cleanup necessary prior to
an instance being destroyed. For example deleting dynamically allocated
objects.

// Continue from Deep Copy example


class Student {
public:
...
~Student();
private:
int* marks; // dynamic attribute
};
Student::~Student() {
delete [] marks; // destroy dynamic attribute
}
Destructor
As with the default constructor, if no explicit destructor is provided, C++
includes an empty one.

// Your code
class Student { // no destructor is provided
};

// Compiler code
class Student {
public:
-Student() { // compiler's default destructor
// no definition/implementation
}
};
Example: Destructor
#include <iostream> int main() {
using namespace std; Student s1(111);
class Student { Student s2(222);
private: return 0;
int idNum; }
public:
Student(int id); // constructor
~Student(); // destructor
}; Output:
Student::Student(int id) { Note: Destroy order reverses
idNum = id; create order
cout << "Object " << idNum
<< " created.\n";
} Object 111 created.
Student::~Student() { Object 222 created.
cout << "Object " << idNum Object 222 destroyed.
<< " destroyed.\n"; Object 111 destroyed.
}
Queries
• Query methods (also called accessors) are methods that are used to
inquire (find out) about the value of an instance’s attributes.

• The key concept with a query method is that it should not change the
value of any of the object’s attributes.

• Types of queries:
• Simple queries (e.g. “What is the value of member x?”)
• Conditional queries (e.g. “Is member x greater than 10?”)
• Derived queries (e.g. “What is the combined value of members x
and y?”)

int getX(); // Query returns the value of attribute x


int getSize(); // Query returns the value of attribute size
Queries
Simple queries often has "getAttribute()" as its method interface, and
consist of only a return statement.
int Student::getidNum() {
return idNum;
}

double Student::getGPA() {
int Test::getXPlusY() {
return gpa;
return (x + y);
}
}
bool Test::isXPositive() {
return (x > 0);
}
Other types of queries should have a descriptive name, and will contain
whatever code is necessary to complete the definition
Updates
• Update methods (also called mutators) contrast with queries. They
change the value of attribute(s) in an object.

• The simplest form of update method will set the value of an attribute to
a specified value, while others will perform much more complex
calculations.

• Simple updates often "setAttribute (parameter)" as its method interface

int setX(int x); // Set the value of attribute x


int setSize(int size); // Set the value of attribute size
Updates
• The benefit of using methods to update attribute is it allows us to
perform data validation before changing the attribute permanently.
• In the following, the setGPA() update method ensure that the new GPA
value is within 0-4.0

int Student::setGPA (double newGPA) {


if ((newGPA >= 0.0) && (newGPA <= 4.0)) {
gpa = newGPA;
return 0; // Return 0 to indicate success
}
else {
return -1; // Return -1 to indicate failure
}
}
const Attributes
• const attributes are attributes that its value cannot be changed throughout the
lifetime of the instance.

• It must be initialized using constructor initializer list.

class Student {
const int idNum; // use keyword "const" to declare
const string name; // const attribute
public:
Student (int id, string name) // overloaded constructor
: idNum(id), name(name) // constructor initializer list
{}
};
int main() {
Student s1(123, "Michael");
}
static Attributes
• Static attributes are attributes that are shared across all instances
of a class.

• The program creates only a single instance of a static attribute,


regardless of how many instances of the class are created.

• We initialize static attributes outside the class declaration using


scope resolution operator "::" (similar as defining methods).

class Student {
static int count; // use keyword "static" to declare
// static attribute
}; // end of class
int Student::count = 0; // initialize count to 0
static Methods
• Static methods operate independently of instances of the class.

• A static method can be invoked without creating an instance of the


class.

• They cannot access any non-static attributes or non-static methods.

• The primary reason to declare static methods is to be able to access


static attributes without creating an instance of the class.

• To invoke a static method independent of an instance, use the scope


resolution operator "::“.
Example: static Attributes
class Student { int main() {
static int count; Student a, b; // create 2 instances
public: cout << "Student count = "
Student() { ++count; } << a.getCount() << endl;
~Student() { --count; } {
static int getCount() { Student c; // create 1 instance
return count; cout << "Student count = "
} << c.getCount() << endl;
}; }
cout << "Student count = "
int Student::count = 0; << Student::getCount()
<< endl;
Student d, e; // create 2 instances
cout << "Student count = "
<< b.getCount() << endl;
Output: return 0;
}
Student count = 2
Student count = 3
Student count = 2
Student count = 4
static Methods
You may invoke static method from instance or independent from
instance.
int main() {
cout << Student::getCount(); // Invokes static
method
// without instance
Student s1; // An instance
cout << s1.getCount(); // Invokes the static method
// via the instance s1
return 0;
}
static const Attributes
• A static const attribute is an attribute that is a constant and shared
across all instances of a class.

• static const attribute must be initialized.

• static const attribute of simple data types can be initialized when


they are declared.

• static const attribute of more complex data types must be initialized


outside the class declaration.
class Student {
public:
static const string university;
static const int postcode = 63100; // simple data
type
};
const string Student::university = "MMU";
static const Attributes
class Student {
public:
static const string university;
static const int postcode = 63100; // simple data
type
};
const string Student::university = "MMU";
int main() {
cout << Student::university << endl Output:
<< Student::postcode << endl;
Student s1; MMU
cout << s1.university << endl 63100
<< s1.postcode << endl; MMU
Student s2; 63100
MMU
cout << s2.university << endl
63100
<< s2.postcode << endl;
return 0;
}
const, static and static const Attributes

To summarize:

• Attributes that you want to “share” across all instances of a


class should be declared as static.

• Attributes that you want to be constant value throughout the


lifetime of an instance should be declared as const.

• Attributes that you want to “share” a constant value across all


instances of a class, should be declared as static const.
const Methods
• We declare const methods to indicate our intention that the methods
should not change the value of any attributes.
• It is a compile-error when there is code trying to change a data
member in a const method.
class Student {
int gpa;
public:
...
int getGPA() const { // const method
gpa = 4.0; // compile-error
return gpa;
}
};
• In general, you should declare all query methods as const to remind you
about the intention of the methods.
• You must declare all query methods as const if you want to be able to
invoke them in a const object.
const Objects
• const objects are objects that all its non-static attributes cannot
be changed after the instance is initialized.

const Student s1 (123); // Declare a constant Student

• You are able to call only methods that are static or const.
• Compiler will prevent you from changing the value of any non-
static or non-const members (atttibutes and methods).
Example: const Objects
class Student {
public:
Student(int id) { // overloaded constructor
this->id = id;
++count;
}
static int getCount() { // static method
Output:
return count;
} 2
int getId() const { // const method 123
return id;
}
234
private:
static int count; // static attribute
int id; // non-static attribute
};
int Student::count = 0; // initialize static attribute
int main() {
const Student s1(123), s2(234); //2 const instances
cout << Student::getCount() << endl //call static method
<< s1.getId() << endl //call const method
<< s2.getId() << endl; //call const method
return 0;
}

You might also like