online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
#include "Clock.h" extern void appl(IClock&); int main() { std::cout.setf(std::ios::boolalpha); Clock c{}; appl(c); }
#include <iostream> #define SHOW(...)\ (void)(std::cout << __FILE__ << ':' << __LINE__ << '\t'\ << #__VA_ARGS__ << " --> " << (__VA_ARGS__)\ << std::endl) #include "IClock.h" void appl(IClock& c) { c.TickUp(); c.Print(std::cout); c.TickUp(); SHOW(c); c.TickUp(); SHOW(c); c.TickUp(); SHOW(c); c.Set(0, 0, 58); SHOW(c); c.TickUp(); SHOW(c); c.TickUp(); SHOW(c); c.TickUp(); SHOW(c); c.Set(0, 59, 58); SHOW(c); c.TickUp(); SHOW(c); c.TickUp(); SHOW(c); }
#ifndef ICLOCK_H #define ICLOCK_H #include <iosfwd> class IClock { public: virtual ~IClock() =default; virtual void Set(int, int, int) =0; virtual void TickUp(int = 1) =0; virtual void Print(std::ostream&) const =0; }; inline std::ostream& operator<<(std::ostream& lhs, const IClock& rhs) { rhs.Print(lhs); return lhs; } #endif
#ifndef CLOCK_H #define CLOCK_H #include <iosfwd> #include <cstring> #include <iostream> #include "IClock.h" #include "LimitCounter.h" #include "OverflowCounter.h" class Clock : public IClock { LimitCounter hours_; OverflowCounter minutes_; OverflowCounter seconds_; public: Clock(int hours = 0, int minutes = 0, int seconds = 0) : hours_{24} , minutes_{60, hours_} , seconds_{60, minutes_} { Set(hours, minutes, seconds); } Clock(const Clock&) =delete; // copy c'tor Clock& operator=(const Clock&) =delete; // copy assignment Clock(Clock&&) =delete; // move c'tor Clock& operator=(Clock&&) =delete; // move assignment virtual void Set(int hours, int minutes, int seconds) override { hours_.SetValue(hours); minutes_.SetValue(minutes); seconds_.SetValue(seconds); } virtual void TickUp(int seconds) override { seconds_.Count(seconds); } virtual void Print(std::ostream&) const override; }; #endif
#include "Clock.h" #include <iostream> #include <iomanip> void Clock::Print(std::ostream& s) const { std::ostream os{s.rdbuf()}; os.fill('0'); os << std::setw(2) << hours_.GetValue() << ':' << std::setw(2) << minutes_.GetValue() << ':' << std::setw(2) << seconds_.GetValue(); }
#ifndef LIMIT_COUNTER_H #define LIMIT_COUNTER_H #include <limits> class LimitCounter { private: int value_{}; const int max_value_{}; public: LimitCounter(int max_value = std::numeric_limits<int>::max()) : value_{0} , max_value_{max_value} {} auto SetValue(int value) { value_ = value; } auto GetValue() const { return value_; } void Count(int amount); virtual bool Count(); virtual void Reset(); }; #endif
#include "LimitCounter.h" void LimitCounter::Count(int amount) { while (amount-- > 0) { Count(); } } bool LimitCounter::Count() { if (++value_ >= max_value_) { value_ = 0; return true; } return false; } void LimitCounter::Reset() { value_ = 0; }
#ifndef OVERFLOW_COUNTER_H #define OVERFLOW_COUNTER_H #include "LimitCounter.h" class OverflowCounter : public LimitCounter { LimitCounter& next_counter_; public: OverflowCounter(const OverflowCounter&) =delete; OverflowCounter& operator=(const OverflowCounter&) =delete; OverflowCounter(OverflowCounter&&) =delete; OverflowCounter& operator=(OverflowCounter&&) =delete; OverflowCounter(int max_value, LimitCounter& next_counter) : LimitCounter{max_value} , next_counter_{next_counter} {} using LimitCounter::Count; virtual bool Count() override; virtual void Reset() override; }; #endif
#include "OverflowCounter.h" bool OverflowCounter::Count() { const auto overflowed = LimitCounter::Count(); if (overflowed) { next_counter_.Count(); } return overflowed; } void OverflowCounter::Reset() { LimitCounter::Reset(); next_counter_.Reset(); }
# A Counter Chain Connected via References Using references instead of pointers to chain the counters. * PRO-s: * Some space is saved in counters (now: `LimitCounter`) that are NOT actually chained. * No run-time tests required to decide whether the chained counter need to be incremented or reset. * CON-s: * If virtual member functions aren't necessary for any other reasons, the "saved space" comes back via the VMT-pointer which is added as "hidden data member" to each class using "runtime polymorphism" (aka. "late binding").
# Applying the "Non Virtual Interface" Idiom Change the class design to apply the NVI-Idiom (= Non Virtual Interface) - Make the currently `public` member function `LimitCounter::Count` and `LimitCounter::Reset` NON-`virtual` and `final`. - From inside these member functions, when the counter value is reset, call new `virtual` member functions, say - `LimitCounter::OverflowAction` and - `LimitCounter::ResetAction` - Implement both EMPTY in class `LimitCounter`. - Overwrite both in class `OverflowCounter` to simply call - `next_counter_.Count()` or - `next_counter_.Reset()` respectively **Note:**\ These two functions may (and should) be private but can still be overridden in the derived class. * * * * * Optional: - Consider the case that - there may be many more such "extension points" like `LimitCounter::OverflowAction` and `LimitCounter::ResetAction` - most of which stay unused in the derived classes. - What are the Pros and Cons?
all: main run run: main ./main main: *.cpp *.h g++ -std=c++14 *.cpp -o $@ clean: -rm -f *.o a.out core main zip: clean zip ../clock-03.zip *.txt *.cpp *.h Makefile .PHONY: all run clean zip

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue