Skip to content

Instantly share code, notes, and snippets.

@mshafae
Created February 28, 2024 18:36
Show Gist options
  • Save mshafae/00875dc88635dfb640278b2259b19fb3 to your computer and use it in GitHub Desktop.
Save mshafae/00875dc88635dfb640278b2259b19fb3 to your computer and use it in GitHub Desktop.
CPSC 120 C++ virtual usage
// Gist https://gist.github.com/mshafae/00875dc88635dfb640278b2259b19fb3
// Filename cpsc120_virtual.cc
// CompileCommand clang++ -std=c++17 cpsc120_virtual.cc
// Demonstrates how virtual works in C++
#include <iostream>
#include <string>
class Fizz {
public:
virtual void PureVirtual() = 0;
void FavoriteColor() { std::cout << "Red " << this << "\n"; }
void FavoriteSeason() { std::cout << "Winter " << this << "\n"; }
};
class Buzz : public Fizz {
public:
void FavoriteColor() { std::cout << "Fall " << this << "\n"; }
};
class Frob : public Buzz {
public:
void PureVirtual() { std::cout << "Not so pure anymore " << this << "\n"; }
void FavoriteColor() { std::cout << "Blue " << this << "\n"; }
// No FavoriteSeason()
};
class Foo {
public:
virtual void SayHi() { std::cout << "Foo saying hi " << this << "\n"; }
void MyName() { std::cout << "My name is Foo " << this << "\n"; }
};
class Bar : public Foo {
public:
void SayHi() { std::cout << "Bar saying hi " << this << "\n"; }
void MyName() { std::cout << "My name is Bar " << this << "\n"; }
};
int main(int argc, char* argv[]) {
// error: variable type 'Fizz' is an abstract class
// unimplemented pure virtual method 'PureVirtual' in 'Fizz'
// Fizz x;
// error: variable type 'Buzz' is an abstract class
// unimplemented pure virtual method 'PureVirtual' in 'Buzz'
// Buzz x;
// We can define Frob because PureVirtual is defined.
Frob x;
// We expect "Not so pure anymore."
x.PureVirtual();
// We expect "Green"
x.FavoriteColor();
// We expect "Fall"
x.FavoriteSeason();
std::cout << "\n";
Foo f;
Bar b;
// We expect "My name is Foo"
f.MyName();
// We expect "Foo saying hi"
f.SayHi();
// We expect "My name is Bar"
b.MyName();
// We expect "Bar saying hi"
b.SayHi();
std::cout << "\n";
Foo* ptr;
ptr = &f;
// We expect "My name is Foo"
ptr->MyName();
// We expect "Foo saying hi"
ptr->SayHi();
// We use the parent type's pointer to point to the derived type.
// Pointers can be re-assigned.
ptr = &b;
// We expect "My name is Bar" but we see "My name is Foo"
ptr->MyName();
// We expect "Bar saying hi".
ptr->SayHi();
std::cout << "\n";
Foo& ref_f = f;
// We expect "My name is Foo"
f.MyName();
// We expect "Foo saying hi"
ref_f.SayHi();
// References can only be bound once, so we need a new one.
Foo& ref_b = b;
// We expect "My name is Bar" but we see "My name is Foo"
ref_b.MyName();
// We use the parent type's reference to alias the derived type
// instance. We expect "Bar saying hi".
ref_b.SayHi();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment