Presentation is loading. Please wait.

Presentation is loading. Please wait.

Classes. Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation.

Similar presentations


Presentation on theme: "Classes. Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation."— Presentation transcript:

1 Classes

2 Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation of a class. In terms of variables, a class would be the type, and an object would be the variable. Usually class’s declarations will be in.h file, while its implementation will be in the.cpp file.

3 Define a plant class Plant { private: bool hasLeaves; doubleheight; }; class body access control Data Members Do we have a plant yet ? NO !!! We have a plan for a plant "Plant.h"

4 Create a plant #include "Plant.h" int main() { Plant myPlant; } Only after that line we have a plant ! “main.cpp" What does this plant look like? ? Did we initialized the members ? NO !!! Lets see what happened… WE DO NOT KNOW

5 Construction Plant myPlant; When we create an instance of a class – a constructor called. When we do not define any – a default constructor is created by the compiler. class Plant { public: Plant() { } private: bool hasLeaves; double height; }; But… It’s empty!!! Well – not exactly. It creates the members : First : hasLeaves Second: height Did we initialized the members ? NO !!! double and bool types contain TRASH by default

6 Construction class Plant { public: Plant() : hasLeaves( true ), height( 1 ) { } private: bool hasLeaves; double height; }; Constructor is a special function of a class. It’s name is the same as the class name. It has no return value It allows members initialization – when they are created. Like that: Now we KNOW: when we create a plant like this: Plant myPlant; We have a plant of height 1, and with leaves.

7 Construction class Plant { public: Plant() : hasLeaves( true ), height( 1 ) { } Plant( bool withLeaves, double theHeight ) : hasLeaves( withLeaves ), height (theHeight) { } private: bool hasLeaves; double height; }; What if we want to create a plant with some parametric member variables? Now we can create another plant ( in main() ): Plant myOtherPlant( false, 1 ); Now we have 2 constructors: Default: Plant() no parameters Another: Plant( bool withLeaves, double theHeight )

8 Construction What if have only non default constructor (or constructors)? class Plant { public: Plant( bool withLeaves, double theHeight ) : hasLeaves( withLeaves ), height (theHeight) { } private: bool hasLeaves; double height; }; Can we now create a plant like that? Plant myPlant; NO If we have at least one constructor – the compiler does not create a default one! We have to do it, IF we want to be able to create a default plant: Plant myPlant;

9 Member functions (methods) class Plant { public: Plant() : hasLeaves( true ), height( 1 ) { } Plant( bool withLeaves, double theHeight ) : hasLeaves( withLeaves ), height (theHeight) { } private: bool hasLeaves; double height; }; Right now we can only create a plant. But a class is also about behavior! Let’s add our plant some member functions.

10 Member functions (methods) class Plant { public: Plant() : hasLeaves( true ), height( 1 ) { } Plant( bool withLeaves, double theHeight ) : hasLeaves( withLeaves ), height (theHeight) { } void Grow() { height += 1; } void Grow( double growBy ) { height += growBy; } private: bool hasLeaves; double height; }; Now we can not only create – but also Grow a plant: Plant myPlant;// height = 1 myPlant.Grow( );// height = 2 myPlant.Grow( 3.5 );// height =5.5

11 Separating Interface from Implementation class Plant { public: Plant(); Plant( bool withLeaves, double theHeight ) ; void Grow(); void Grow( double growBy ); private: bool hasLeaves; double height; }; #include “Plant.h” Plant::Plant() : hasLeaves( true ), height( 1 ) { } Plant:: Plant( bool withLeaves, double theHeight ) : hasLeaves( withLeaves ), height (theHeight) { } void Plant::Grow() { height += 1; } void Plant::Grow( double growBy ) { height += growBy; } Plant.h Plant.cpp Is this the best we can do? No – short functions should be inlined!

12 Default parameters class Plant { public: Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } void Grow(double growBy = 1) { height += growBy ; } private: bool hasLeaves; double height; }; Same functionality: Plant myPlant;// height = 1 myPlant.Grow( );// height = 2 myPlant.Grow( 3.5 );// height = 5.5 But less code! Can we create a plant like this? Plant otherPlant(false); Plant anotherPlant(2.5);

13 Problem? class Plant { public: Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } void Grow(double growBy = 1) { height += growBy ; } private: bool hasLeaves; double height; }; Plant otherPlant(false); works and creates Plant without leaves and with height=1 - OK Plant otherPlant(2.5); works and creates Plant with leaves and with height=1 – Huh???

14 Problem? class Plant { public: Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } void Grow(double growBy = 1) { height += growBy ; } private: bool hasLeaves; double height; }; Plant otherPlant(2.5); calls Plant(bool withLeaves) after converting 2.5 to bool (to a value true) Not what we wanted! This definition is equivalent to defining 3 constructors: Plant(); Plant(bool withLeaves); Plant(bool withLeaves, double theHeight);

15 Solution! class Plant { public: Plant( double theHeight ) : hasLeaves( true ), height (theHeight) { } Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } void Grow(double growBy = 1) { height += growBy ; } private: bool hasLeaves; double height; }; Now Plant otherPlant(2.5); calls Plant(double theHeight) as we wanted. But how does it know what we want? And what will Plant otherPlant(1); do? We add another constructor, that gets only height as a parameter:

16 Overload resolution Step 1: Find candidates: Same name and viable Step 2: Find viable functions: Same number of arguments. Parameters can be converted to the types specified at function declaration. Step 3: Select best matching viable function: Determined by number of conversions needed. Several viable functions with the same number of conversions needed cause compilation error, due to ambiguity.

17 Overload resolution -example void f( int i ) { }; void f( double d = 4.0, int k = 1) { }; (1) f( 5.0 ); // called void f( double d = 4.0, int k = 1) (2) f( 5 ); // void f( int i ) (3) f( true); // Ambiguity error ! Both viable functions //need one conversion ! Step 1: same function name =>candidates. Step 2: viable functions. Step 3: select best matching viable. Go back to slide 14 – Plant constructor.

18 Construction – the details What is the difference between and Member variables are created before any class code is executed, using the values in the initialization line of the constructor If no values are given – the default construction is used: default (parameterless) constructor for classes no initialization (random value) for built-in types The first option is better – why? Plant( bool withLeaves = true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } Plant( bool withLeaves = true, double theHeight = 1) { hasLeaves = withLeaves; height = theHeight; }

19 Construction – the details better than It is obvious that fields are being initialized – easier to understand Better performance for members that are classes Legal even if there is no default constructor for the member Legal even if the member cannot be assigned In particular, the only way to initialize const and reference members Better suited for (multiple) inheritance (later in the course) Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } Plant( bool withLeaves=true, double theHeight = 1) { hasLeaves = withLeaves; height = theHeight; }

20 Array member construction Suppose we want to define a class that represents a flower clock, and contains an array of plants: class FlowerClock { public: FlowerClock() {} private: Plant plants[24]; /* Some members */ }; What happens during initialization of FlowerClock? How can we initialize all members to have height 2?

21 Array member construction class FlowerClock { public: FlowerClock() {} private: Plant plants[24]; /* Some members */ }; Reminder: 1. Member variables are created before any class code is executed, using the values in the initialization line of the constructor 2. If no values are given – the default construction is used to create the member 3. The default construction for arrays is: If elements are classes – initialize them using default (parameterless) constructor If elements are built-in types - no initialization (random value) So what we have is an array of 24 plants, each with values initialized by the default constructor of Plant – with leaves and with height=1

22 Array member construction class FlowerClock { public: FlowerClock() {} private: Plant plants[24]; /* Some members */ }; How can we initialize all plants to have height 2? For a regular array variable, we can write: Plant couple[2] = {Plant(true,2), Plant(false,2)}; For a class member that is an array – there is no way! Array members are always initialized in the default manner – no explicit values allowed! To put non-default values, we must write code inside the constructor: FlowerClock::FlowerClock() { for (size_t i=0; i<24; i++) { plants[i] = Plant(true, 2); // Assumes Plant can be assigned! }


Download ppt "Classes. Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation."

Similar presentations


Ads by Google