Upload
tranthien
View
273
Download
3
Embed Size (px)
Citation preview
1
CSCI 104Classes
Mark Redekopp
David Kempe
2
CLASSES
3
C Structs
• Needed a way to group values that are related, but have different data types
• NOTE: struct has changed in C++!
– C• Only data members
• Some declaration nuances
– C++• Like a class (data + member functions)
• Default access is public
struct Person{
char name[20];
int age;
};
int main()
{
// Anyone can modify
// b/c members are public
Person p1;
p1.age = -34;
// probably not correct
return 0;
}
4
Classes & OO Ideas• In object-oriented programming languages (C++) classes are used as the
primary way to organize code
• Encapsulation
– Place data and operations on data into one code unit
– Keep state hidden/separate from other programmers via private members
• Abstraction
– Depend only on an interface!
• Ex. a microwave…Do you know how it works?But can you use it?
– Hide implementation details to create low degree of coupling between different components
• Polymorphism & Inheritance
struct Machine{
Piece* pieces;
Engine* engine;
};
int main()
{
Machine m;
init_subsystemA(&m);
change_subsystemB(&m);
replace_subsystemC(&m);
m.start();
// Seg. Fault!! Why?
}
Protect yourself from users & protect your users from themselves
5
Coupling
• Coupling refers to how much components depend on each other's implementation details (i.e. how much work it is to remove one component and drop in a new implementation of it)– Placing a new battery in your car vs. a new engine
– Adding a USB device vs. a new video card to your laptop
• OO Design seeks to reduce coupling as much as possible by– Creating well-defined interfaces to change (write) or access (read) the
state of an object
– Enforcing those interfaces are adhered to
• Private vs. public
– Allow alternate implementations that may be more appropriate for different cases
6
C++ Classes
• A composition mechanism– Create really large and powerful software systems from tiny
components
– Split things up into manageable pieces
• Somewhat of a bottom up approach (define little pieces that can be used to compose larger pieces)
– Delegation of responsibility
• An abstraction and encapsulation mechanism– Make functionality publicly available, but hide data & implementation
details
• A mechanism for polymorphism– More on this later
7
C++ Classes: Overview
• What are the main parts of a class?
– Member variables
• What data must be stored?
– Constructor(s)
• How do you build an instance?
– Member functions
• How does the user need to interact with the stored data?
– Destructor
• How do you clean up an after an instance?
8
C++ Classes: Overview
• Member data can be public or private (for now)– Defaults is private (only class functions can access)
– Must explicitly declare something public
• Most common C++ operators will not work by default (e.g. ==, +, <<, >>, etc.)– You can't cout an object ( cout << myobject; won't work )
– The only one you get for free is '=' and even that may not work the way you want (more on this soon)
• Classes may be used just like any other data type (e.g. int)– Get pointers/references to them
– Pass them to functions (by copy, reference or pointer)
– Dynamically allocate them
– Return them from functions
9
this Pointer• How do member functions know which
object’s data to be operating on?
• d1 is implicitly passed via a special pointer call the ‘this’ pointer
#include<iostream>
#include “deck.h”
int main(int argc, char *argv[]) {
Deck d1, d2;
d1.shuffle();
d1.shuffle();
...
}
#include<iostream>
#include “deck.h”
void Deck::shuffle()
{
cut(); // calls cut()
// for this object
for(i=0; i < 52; i++){
int r = rand() % (52-i);
int temp = cards[r];
cards[r] = cards[i];
cards[i] = temp;
}
}
de
ck
.cp
pp
oke
r.cp
p
d1 i
s i
mp
licit
ly
passed
to
sh
uff
le()
41 27 8 39 25 4 11 17cards[52]
1top_index d1
0x2a0
int main() { Deck d1;
d1.shuffle();
}
void Deck::shuffle(Deck *this)
{
this->cut(); // calls cut()
// for this object
for(i=0; i < 52; i++){
int r = rand() % (52-i);
int temp = this->cards[r];
this->cards[r] = this->cards[i];
this->cards[i] = temp;
}
}
de
ck
.cp
p
Compiler-generated codeActual code you write
0x2a0
d237 21 4 9 16 43 20 39cards[52]
0top_index
0x7e0
this
10
Exercises
• cpp/cs104/classes/this_scope
11
Another Use of 'this'
• This can be used to resolve scoping issues with similar named variables
class Student {
public:
Student(string name, int id, double gpa);
~Student(); // Destructor
private:
string name;
int id;
double gpa;
};
Student::Student(string name, int id, double gpa)
{ // which is the member and which is the arg?
name = name; id = id; gpa = gpa;
}
Student::Student(string name, int id, double gpa)
{ // Now it's clear
this->name = name;
this->id = id;
this->gpa = gpa;
}
12
C++ Classes: Constructors• Called when a class is instantiated
– C++ won't automatically initialize member variables
– No return value
• Default Constructor
– Can have one or none in a class
– Basic no-argument constructor
– Has the name ClassName()
– If class has no constructors, C++ will make a default
• But it is just an empty constructor (e.g. Item::Item() { } )
• Overloaded Constructors
– Can have zero or more
– These constructors take in arguments
– Appropriate version is called based on how many and what type of arguments are passed when a particular object is created
– If you define a constructor with arguments you should also define a default constructor
class Item
{ int val;
public:
Item(); // default const.
Item(int v); // overloaded
};
13
Identify that Constructor
• Prototype what constructors are being called here
#include <string>
#include <vector>
using namespace std;
int main()
{
string s1;
string s2("abc");
vector<int> dat(30);
return 0;
}
14
Identify that Constructor
• Prototype what constructors are being called here
• s1
– string::string() // default constructor
• s2
– string::string(const char* )
• dat
– vector<int>::vector<int>( int );
#include <string>
#include <vector>
using namespace std;
int main()
{
string s1;
string s2("abc");
vector<int> dat(30);
return 0;
}
15
Exercises
• cpp/cs104/classes/constructor_init
16
Consider this Struct/Class• Examine this struct/class definition… #include <string>
#include <vector>
using namespace std;
struct Student
{
string name;
int id;
vector<double> scores;
// say I want 10 test scores per student
};
int main()
{
Student s1;
}
string name
int id
scores
17
Composite Objects• Fun Fact: Memory for an object comes alive before the code
for the constructor starts at the first curly brace '{'#include <string>
#include <vector>
using namespace std;
struct Student
{
string name;
int id;
vector<double> scores;
// say I want 10 test scores per student
Student() /* mem allocated here */
{
// Can I do this to init. members?
name("Tommy Trojan");
id = 12313;
scores(10);
}
};
int main()
{
Student s1;
}
string name
int id
scores
18
Composite Objects• You cannot call constructors on data members once the
constructor has started (i.e. passed the open curly '{' )– So what can we do??? Use initialization lists!
#include <string>
#include <vector>
using namespace std;
struct Student
{
string name;
int id;
vector<double> scores;
// say I want 10 test scores per student
Student() /* mem allocated here */
{
// Can I do this to init. members?
name("Tommy Trojan");
id = 12313;
scores(10);
}
};
int main()
{
Student s1;
}
string name
int id
scores
This would be
"constructing"
name twice. It's
too late to do it in
the {…}
19
Constructor Initialization Lists
• Though you do not see it, realize that the default constructors are implicitly called for each data member before entering the {…}
• You can then assign values but this is a 2-stepprocess
Student::Student()
{
name = "Tommy Trojan";
id = 12313
scores.resize(10);
}
Student::Student() :
name(), id(), scores()
// calls to default constructors
{
name = "Tommy Trojan";
id = 12313
scores.resize(10);
}
If you write this…The compiler will still generate this.
20
Constructor Initialization Lists
• Rather than writing many assignment statements we can use a special initialization list technique for C++ constructors– Constructor(param_list) : member1(param/val), …, memberN(param/val)
{ … }
• We are really calling the respective constructors for each data member
Student:: Student() /* mem allocated here */
{
name("Tommy Trojan");
id = 12313;
scores(10);
}
Student::Student() :
name("Tommy"), id(12313), scores(10)
{ }
You can't call member
constructors in the {…}
You would have to call the member
constructors in the initialization list context
21
Constructor Initialization Lists
• You can still assign values in the constructor but realize that the default constructors will have been called already
• So generally if you know what value you want to assign a data member it's good practice to do it in the initialization list
Student::Student()
{
name = "Tommy Trojan";
id = 12313
scores.resize(10);
}
Student::Student() :
name(), id(), scores()
// calls to default constructors
{
name = "Tommy Trojan";
id = 12313
scores.resize(10);
}
You can still assign data
members in the {…}
But any member not in the initialization list will
have its default constructor invoked before the
{…}
22
Exercises
• cpp/cs104/classes/constructor_init2
23
Member Functions
• Have access to all member variables of class
• Use “const” keyword if it won't change member data
• Normal member access uses dot (.) operator
• Pointer member access uses arrow (->) operator
class Item
{ int val;
public:
void foo();
void bar() const;
};
void Item::foo() // not Foo()
{ val = 5; }
void Item::bar() const
{ }
int main()
{
Item x;
x.foo();
Item *y = &x;
(*y).bar();
y->bar(); // equivalent
return 0;
}
24
Exercises
• cpp/cs104/classes/const_members
• cpp/cs104/classes/const_members2
• cpp/cs104/classes/const_return
25
C++ Classes: Destructors
• Called when a class goes out of scope or is freed from the heap (by “delete”)
• Why use it?
– Not necessary in simple cases
– Clean up resources that won't go away automatically (e.g. stuff you used “new” to create in your class member functions or constructors
• Destructor
– Has the name ~ClassName()
– Can have one or none
– No return value
– Destructor (without you writing any code) will automatically call destructor of any data member objects…but NOT what data members point to!
• You only need to define a destructor if you need to do more than that (i.e. if you need to release resources, close files, deallocate what pointers are point to, etc.)
26
C++ Classes: Other Notes• Classes are generally split across two
files– ClassName.h – Contains interface
description
– ClassName.cpp – Contains implementation details
• Make sure you remember to prevent multiple inclusion errors with your header file by using #ifndef, #define, and #endif#ifndef CLASSNAME_H
#define CLASSNAME_H
class ClassName { … };
#endif
#ifndef ITEM_H
#define ITEM_H
class Item
{ int val;
public:
void foo();
void bar() const;
};
#endif
#include "item.h"
void Item::foo()
{ val = 5; }
void Item::bar() const
{ }
item.h
item.cpp
27
CONDITIONAL COMPILATION
28
Multiple Inclusion
• Often separate files may #include's of the same header file
• This may cause compiling errors when a duplicate declaration is encountered– See example
• Would like a way to include only once and if another attempt to include is encountered, ignore it
string.h
class string{
... };
#include "string.h"
class Widget{
public:
string s;
};
widget.h
#include "string.h"
#include "widget.h"
int main()
{ }
main.cpp
class string { // inc. from string.h
};
class string{ // inc. from widget.h
};
class Widget{
... }
int main()
{ }
main.cpp after preprocessing
29
Conditional Compiler Directives
• Compiler directives start with '#'– #define XXX
• Sets a flag named XXX in the compiler
– #ifdef, #ifndef XXX … #endif• Continue compiling code below
until #endif, if XXX is (is not) defined
• Encapsulate header declarations inside a– #ifndef XX
#define XX…#endif
String.h
#ifndef STRING_H
#define STRING_H
class string{
... };
#endif
#include "string.h"
class Widget{
public:
string s;
};
Character.h
#include "string.h"
#include "string.h"
main.cpp
class string{ // inc. from string.h
};
class Widget{ // inc. from widget.h
...
main.cpp after preprocessing
30
Conditional Compilation• Often used to compile
additional DEBUG code– Place code that is only needed for
debugging and that you would not want to execute in a release version
• Place code in a #ifdefXX...#endif bracket
• Compiler will only compile if a #define XX is found
• Can specify #define in:– source code
– At compiler command line with (-Dxx) flag• g++ -o stuff –DDEGUG stuff.cpp
stuff.cpp
int main()
{
int x, sum=0, data[10];
...
for(int i=0; i < 10; i++){
sum += data[i];
#ifdef DEBUG
cout << "Current sum is ";
cout << sum << endl;
#endif
}
cout << "Total sum is ";
cout << sum << endl;
$ g++ -o stuff –DDEBUG stuff.cpp
31
PRE SUMMER 2016
32
Example Code• Login to your VM, start a terminal
• Best approach – Clone Lecture Code Repo
– $ git clone [email protected]:usc-csci104-fall2015/r_lecture_code.git lecture_code
– $ cd lecture_code/coninit
– $ make coninit
• Alternate Approach – Download just this example
– Create an 'lecture_code' directory
– $ wget http://ee.usc.edu/~redekopp/ee355/code/coninit.cpp
– $ make coninit