Skip to content

Week 4

Week 4 Discussion

Here is the code we went over in discussion.

#include <iostream>
#include <string>
class Animal
{
public:
    int name = 0;
    virtual void sleep()
    {
        std::cout << "sleeping...zzz" << '\n';
    }
};

class Dog : public Animal
{
public:
    // change this to virtual
    int dogname = -1;
    virtual void sleep()
    {
        std::cout << "a dog is sleeping...zzz" << '\n';
    }
    void bark()
    {
        std::cout << "bark bark" << '\n';
    }
};

int main()
{
    // will this work?
    dog_to_animal->bark();
    //__Animal_bark()

    // non-virtual sleep
    dog_to_animal->sleep();
    // __Animal_sleep()


    //Animal* dog_to_animal = new Dog();
    //std::cout << dog_to_animal->dogname << '\n';

    // will this work? --subtyping
    Dog* animal_to_dog = new Animal();

}
#include <iostream>
#include <string>
class Shape
{
public:
    virtual double area(){return -1;}
};

class Circle : public Shape
{
    double r;
public:
    Circle (double radius) {r = radius;}
    // change this to virtual
    double area()
    {
        return r*r*3.14159265;
    }
};

class Rectangle : public Shape
{
    double a, b;
public:
    Rectangle (double _a, double _b) {a = _a; b = _b;}
    // change this to virtual
    double area()
    {
        return a*b;
    }
};

void calculate_area_1(Shape* s)
{
    std :: cout << s->area() << '\n';
}

// pass by reference
void calculate_area_2(Shape& s)
{
    std :: cout << s.area() << '\n';
}

// pass by value: create a new instance
void calculate_area_3(Shape s)
{
    std :: cout << s.area() << '\n';
}

int main()
{
    Circle c = Circle(1.0);
    Rectangle r = Rectangle(1.0, 1.0);
    // pass by pointer
    calculate_area_1(&c);
    calculate_area_1(&r);

    // pass by reference
    //calculate_area_2(c);
    //calculate_area_2(r);

    // pass by value: create a new instance
    //calculate_area_3(c);
    //calculate_area_3(r);
}
#include <iostream>
#include <string>
#include <functional>
class Animal
{
public:
    int name = 0;
    void sleep(){}
};

class Dog : public Animal
{
public:
    int name = 3;
    // change this to virtual
    void sleep(){}
    void bark(){}
};

Animal animal_clone()
{
}

Dog dog_clone()
{
}

// Q: dog_clone ? animal_clone
// why?

void animal_sub_dog(std::function<Dog()> func)
{
    // maybe I'll call bark here
    // dog = func();  dog.bark();
    std::cout << "animal_clone is a subtype of dog_clone" << '\n';
}

void dog_sub_animal(std::function<Animal()> func)
{
    // animal = func(); animal.dosomething
    // all functions for animals work for dog
    std::cout << "dog_clone is a subtype of animal_clone" << '\n';
}
int main()
{
    // Clone:  animal_clone <: dog_clone?
    // what dog_clone can do, animal_clone can do
    // think of a function that takes dog_clone as input, but animal_clone cannot work
    animal_sub_dog(animal_clone);
    // Clone:  dog_clone <: animal_clone?
    // what animal_clone can do, dog_clone can do
    dog_sub_animal(dog_clone);
    // pointer follows covariance
    // Dog <: Animal
    // Animal* dog_to_animal = new Dog();
    // Dog* animal_to_dog = new Animal();
}
#include <iostream>
#include <string>
#include <functional>
class Animal
{
public:
    int name = 0;
    void sleep(){}
    virtual void f(Animal a) {}
};

class Dog : public Animal
{
public:
    int dog_name = 1;
    // change this to virtual
    void sleep(){}
    void bark(){}
    virtual void f(Dog d) {}
};

void animal_f(Animal a) {}

void dog_f(Dog d) {}

void animal_sub_dog(std::function<void(Dog)> func)
{
    //Dog dog;
    //func(dog)  (dog -> animal can work)
    // the only application that is the difference will be the argument
    std::cout << "animal_f is a subtype of dog_f" << '\n';
}

void dog_sub_animal(std::function<void(Animal)> func)
{
    // Animal animal;
    // func(animal);
    // all functions for animals work for dog
    std::cout << "dog_f is a subtype of animal_f" << '\n';
}
int main()
{
    // animal_f <: dog_f?
    animal_sub_dog(animal_f);
    // dog_f <: animal_f?
    dog_sub_animal(dog_f);
    // another way:
    // animal_f(animal) works, dog_f(animal) doesn't work
    // animal_f(dog) works, dog_f(dog) works
    // ===> dog_f x<: animal_f

    // dog_f(animal) dosen't work
    // dog_f(dog) works, animal_f(dog) works
    // ===> animal_f <: dog_f
}
#include <iostream>
#include <string>
#include <functional>
class Animal
{
public:
    int name = 0;
    void sleep(){}
    //virtual Animal* clone(Animal* a) {}
};

class Dog : public Animal
{
public:
    int dog_name = 1;
    // change this to virtual
    void sleep(){}
    void bark(){}
    //Dog* clone(Dog* a) override {}
};
Animal dog_to_animal(Dog a){}
Dog animal_to_dog(Animal b){}
void one_sub_two(std::function<Dog(Animal)> func)
{
    // maybe I'll call bark here
    // dog = func();  dog.bark();
    std::cout << "dog_to_animal is a subtype of animal_to_dog" << '\n';
}

void two_sub_one(std::function<Animal(Dog)> func)
{
    // all functions for animals work for dog
    std::cout << "animal_to_dog is a subtype of dog_to_animal" << '\n';
}
int main()
{
    one_sub_two(dog_to_animal);
    two_sub_one(animal_to_dog);
    // animal->dog <: animal->animal <: dog->animal
    // dog->dog ? animal->animal
}
#include <iostream>
#include <string>
#include <functional>
class Animal
{
public:
    int name = 0;
    void sleep(){}
    //virtual Animal* clone(Animal* a) {}
};

class Dog : public Animal
{
public:
    int dog_name = 1;
    // change this to virtual
    void sleep(){}
    void bark(){}
    //Dog* clone(Dog* a) override {}
};
Dog dog_to_dog(Dog a){}
Animal animal_to_animal(Animal b){}
void one_sub_two(std::function<Animal(Animal)> func)
{
    // maybe I'll call bark here
    // dog = func();  dog.bark();
    std::cout << "dog_to_dog is a subtype of animal_to_animal" << '\n';
}

void two_sub_one(std::function<Dog(Dog)> func)
{
    // all functions for animals work for dog
    std::cout << "animal_to_animal is a subtype of dog_to_dog" << '\n';
}
int main()
{
    one_sub_two(dog_to_dog);
    two_sub_one(animal_to_animal);
    // animal->dog <: animal->animal <: dog->animal
    // dog->dog ? animal->animal
}
#include <iostream>
#include <string>
#include <functional>
class Food
{
public:
    void eaten(){}
};
class DogFood : public Food
{
public:
    void eaten(){}
};

class Animal
{
public:
    int name = 0;
    void sleep(){}
};

class Dog : public Animal
{
public:
    int dog_name = 1;
    void sleep(){}
    void bark(){}
};
DogFood animal_dogfood(Animal a){}
Food dog_food(Dog b){}
void one_sub_two(std::function<Food(Dog)> func)
{
    // maybe I'll call bark here
    // dog = func();  dog.bark();
    std::cout << "animal_dogfood is a subtype of dog_food" << '\n';
}

void two_sub_one(std::function<DogFood(Animal)> func)
{
    // all functions for animals work for dog
    std::cout << "dog_food is a subtype of animal_dogfood" << '\n';
}
int main()
{
    one_sub_two(animal_dogfood);
    two_sub_one(dog_food);
    // animal->dog <: animal->animal <: dog->animal
    // dog->dog ? animal->animal
}