summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--03-09.md4
-rw-r--r--03-11.md216
2 files changed, 220 insertions, 0 deletions
diff --git a/03-09.md b/03-09.md
index 1ed6217..54e5406 100644
--- a/03-09.md
+++ b/03-09.md
@@ -548,3 +548,7 @@ herbivore::herbivore(double init_size, double init_rate, double init_need) : ani
//No work is done here, except calling the animal constructor
}
```
+
+---
+
+[03/11 ->](03-11.md)
diff --git a/03-11.md b/03-11.md
new file mode 100644
index 0000000..042c6a1
--- /dev/null
+++ b/03-11.md
@@ -0,0 +1,216 @@
+[\<- 03/09](03-09.md)
+
+---
+
+# Virtual Member Functions
+
+## Example
+
+```
+class person{
+ public:
+ person(std::string name = "empty", int age = 0){
+ this->name = name;
+ this->age = age;
+ }
+
+ void print_name() const {
+ std::cout << "Name is: " << get_name() << std::endl;
+ }
+
+ protected:
+ std::string get_name() const { return name; };
+
+ private:
+ std::string name;
+ int age;
+};
+
+class professor : public person{
+ public:
+ professor(std::string name = "empty", int age = 40, double salary = 0, bool nice = true) : person(name, age), salary(salary), nice(nice){};
+
+ //Overriding the get_name function
+ //Now this is a public function of this class
+ std::string get_name() const{
+ return (person::get_name() + ", he is nice!");
+ }
+
+ private:
+ double salary;
+ bool nice;
+};
+
+int main(int argc, const char* argv[]){
+ professor myProf("Ben", 36);
+ myProf.print_name();
+ return 0;
+}
+
+---
+
+//The output is:
+Name is: Ben
+```
+
+## An example with a virtual
+
+```
+class person{
+ public:
+ person(std::string name = "empty", int age = 0){
+ this->name = name;
+ this->age = age;
+ }
+
+ void print_name() const {
+ std::cout << "Name is: " << get_name() << std::endl;
+ }
+
+ protected:
+ //This is a virtual now!!!
+ virtual std::string get_name() const { return name; };
+
+ private:
+ std::string name;
+ int age;
+};
+
+class professor : public person{
+ public:
+ professor(std::string name = "empty", int age = 40, double salary = 0, bool nice = true) : person(name, age), salary(salary), nice(nice){};
+
+ //Overriding the get_name function
+ //Now this is a public function of this class
+ std::string get_name() const{
+ return (person::get_name() + ", he is nice!");
+ }
+
+ private:
+ double salary;
+ bool nice;
+};
+
+int main(int argc, const char* argv[]){
+ professor myProf("Ben", 36);
+ myProf.print_name();
+ return 0;
+}
+```
+
+- If we use `virtual std::string get_name() const { return name; };`, then the output is:
+ - `Name is: Ben, he is nice!`
+
+- If we use `std::string get_name() const { return name; };`, then the output is:
+ - `Name is: Ben`
+
+## Example: game Class
+
+- **Virtual member functions** are a new kind of member function that allows certain aspects of activating a function to be delayed until a program is actually running
+- To make the explanation of virtual functions concrete, we'll present an example of a class called **game**, which will mke it easier for us to write programs that play various two-player games such as chess, checkers, or Othello
+
+```
+class game{
+ public:
+ //ENUM TYPE
+ enum who { HUMAN, NEUTRAL, COMPUTER }; //Possible game outcomes
+
+ //CONSTRUCTOR and DESTRUCTOR
+ game() { move_number = 0; };
+ virtual ~game() {};
+
+ //PUBLIC MEMBER FUNCTIONS
+ //The play function should not be overridden. It plays once game, with the human player moving first and the computer second
+ //The computer uses an alpha-beta look ahead algorithm to select its moves. The return value is the winner of the game (or NEUTRAL for a tie)
+ who play();
+
+ protected:
+ //OPTIONAL VIRTUAL FUNCTIONS (overriding these is optional)
+ virtual void display_message(const std::string& message) const;
+ virtual std::string get_user_move() const;
+ virtual who last_mover() const { return (move_number % 2 == 1 ? HUMAN : COMPUTER); };
+ virtual int moves_completed() const { return move_number; };
+ virtual who next_mover() const { return (move_number % 2 == 0 ? HUMAN : COMPUTER); };
+ virtual who opposite(who player) const { return (player == HUMAN ? COMPUTER : HUMAN); };
+ virtual who winning() const;
+
+ //VIRTUAL FUNCTIONS THAT MUST BE OVERRIDDEND (The overriding function function should call the original when it finishes)
+ //Have the next player make a specified move:
+ virtual void make_move(const std::string& move) { ++move_number; };
+ //Restart the game from the beginning:
+ virtual void restart() { move_number = 0; };
+
+ //PURE VIRTUAL FUNCTIONS (these must be provided for each derived class
+ //Return a pointer to a copy of myself:
+ virtual game* clone() const = 0;
+ //Computer all the moves that the next player can make:
+ virtual void computer_moves(std::queue<std::string>& moves) const = 0;
+ //A pure virtual function is indicated by "= 0" before the end of the semicolon in the prototype
+ //The class does not provide any implementation of a pure virtual function
+
+ private:
+ //MEMBER VARIABLES
+ int move_number; //Number of moves made so far
+ //...
+};
+```
+
+## Protected Members
+
+```
+protected:
+ //OPTIONAL VIRTUAL FUNCTIONS (overriding these is optional)
+ virtual void display_message (const std::string& message) const;
+```
+
+- The keyword **protected** indicates that the items that follow will be a new kind of member, somewhat between *public* and *private*
+- A protected member can be used (and overridden) by a derived class - but apart from within a derived class, any protected member is private; It cannot be used elsewhere
+
+## Virtual Member Functions
+
+- The first protected member function in the game class is `display_message`
+
+```
+game::who game::play(){
+ display_message("Welcome!");
+ ...
+}
+```
+
+- When we play the game, the welcome message is printed at the start
+- But, suppose that we write a game that needs to display messages by some other method
+- Our derived class will inherit all the game class members, but it can override any method that it doesn't like
+
+- Perhaps we want our Connect Four game to print "\*\*\*" before each displayed message (just to make the messages more exciting)
+- We could override the `display_message` function so that `connect4::display_message` first prints "\*\*\*" and then prints the message
+- With this approach, when the `play` method begins, it will activate `display_message("Welcome!")`, but what will this print?
+ - If it uses `game::display_message`, then the word "Welcome!" appears by itself
+ - If it uses `connect4::display_message`, then "\*\*\*Welcome!"
+
+### When Onve Member Function Activates Another
+
+- Normally, when a member function `f()` activates another member function `g()`, the version of `g()` that is actually activated comes from the same class as the function `f()`
+- This behavior occurs even if the activated function `g` is later overridden, and `f` is activated by an object of the derived class
+- In this example, this means that `game::play` normally would use `game::display_message`, even if a derived object activates the play method
+- Solution: use "**virtual**"
+
+### Activating a Virtual Member Function
+
+- Whenever a **virtual** member function is activated, **the data type of the activating object is examined when the program is running**, and the correct version of the function is used
+- For a virtual member function, the choice of which version of the function to use is never made until the program is running
+- At run time, **the program examines the data type of the object** that activated the method, and thereby uses the correct version of the function
+
+### Pure Virtual Functions and Abstract Classes
+
+- A pure virtual function is indicated by "= 0" before the end of the semicolon in the prototype
+- The class does not provide any implementation of a pure virtual function
+- Because there is no implementation, any class with a pure virtual function is called an **abstract class** and **no instances of an abstract class may appear in a program**
+- Abstract classes are used as base classes, and it is up to the derived class to provide an implementation for each pure virtual function
+
+## Summary
+
+- Object-oriented programming supports reusable components by permitting new derived classes to be declared, which automatically inherit all members of an existing base class
+- All members of a base class are inherited by the derived class, but only the non-private members of the base class can be accessed by the programmer who implements the derived class
+- The connection between a derived class and its base class can often be characterized by the "is-a" relationship
+- An abstract base class (such as the game class) can provide a common framework that is needed by many derived classes
+- An abstract base class has one or more pure virtual functions, which are functions that must be overridden before the class can be used