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); }
#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 <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 COUNTER_H #define COUNTER_H #include <limits> class LimitCounter { private: int value_{}; const int max_value_{}; virtual void OverflowAction() {} virtual void ResetAction() {} 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); void Count(); void Reset(); }; #endif
#include "LimitCounter.h" void LimitCounter::Count(int amount) { while (amount-- > 0) { Count(); } } void LimitCounter::Count() { if (++value_ >= max_value_) { value_ = 0; OverflowAction(); } } void LimitCounter::Reset() { value_ = 0; ResetAction(); }
#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} {} virtual void OverflowAction() override; virtual void ResetAction() override; }; #endif
#include "OverflowCounter.h" void OverflowCounter::OverflowAction() { next_counter_.Count(); } void OverflowCounter::ResetAction() { next_counter_.Reset(); }
#include <iostream> #define SHOW(...)\ (void)(std::cout << __FILE__ << ':' << __LINE__ << '\t'\ << #__VA_ARGS__ << " --> " << (__VA_ARGS__)\ << std::endl) #include "IClock.h" void appl(IClock& c) { SHOW(c); 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); c.TickUp(60); SHOW(c); c.TickUp(600); SHOW(c); }
# Apply NVI-Idiom ("Non-Virtual Interface") This solution not only shows "NVI" to the minimal amount necessary to solve forwarding "overflows" and "resets" but already provided more extension points … just "in case". - PRO-s: - More flexibility / adaptability - CON-s: - Potentially calls to many subroutines that do nothing but return immediately if many of the provided extension points aren't actually used.
# Adding an Interface `ICounter` To add an interface `ICounter` to class `LimitCounter`, with the member functions `Count` and `Reset` remember: - in the interface these need to be pure `virtual` but - in accordance the NVI-idiom in `LimitCounter` these should be `override final` If you are good with the above, start right away. Otherwise, if you need a bit more of guidance, read on. Adding an Interface to class `LimitCounter`means you first add a new file defining the interface. It can look a bit like this (of course, this needs to be wrapped in the usual include guards and the new file must be included at the appropriate places): ``` class ICounter { public: virtual ~ICounter() =delete; virtual void Count() =0; virtual void Reset() =0; }; ``` - Having `LimitCounter` implement that interface means as little as changing it like shown below: - The current content can stay as it was … - … unless you want to clearly document which member functions implement some interface function (using `override`) … - … and that your design adheres to the NVI idiom (using `final`) at the appropriate places. ``` class LimitCounter : public ICounter { ... }; ``` One purpose of that interface is to use it for the chain counter reference, so the actual counter coupled to lower stages gets more freedom what it can be. - This requires TWO changes to `OverflowCounter`: - Once as type for `next_counter_` - Second as constructor argument type! * * * * * Optional/Advanced Discuss based on the LSP – i.e. for each DERIVED class (when accessed via reference or pointer) – may be used in place of any (direct or indirect) of its BASE classes, including interfaces. NOTE: The following question may "theoretically" be answered based on the LSP only, but the MINIMAL way to IMPLEMENT it requires the use of private inheritance combined with virtual base classes, so it's definitely NOT for beginners. - If an `OverflowCounter` should only be accepted in place of `ICounter` but NOT in place or `LimitCounter`, which changes would need to be made?
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-04.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