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) { 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); }
#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 HasOverflowed() {} virtual void HasResetted() {} public: LimitCounter(int max_value = std::numeric_limits<int>::max()) : value_{0} , max_value_{max_value} {} void SetValue(int value) { value_ = value; } int 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; HasOverflowed(); } } void LimitCounter::Reset() { value_ = 0; HasResetted(); }
#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 HasOverflowed() override; virtual void HasResetted() override; }; #endif
#include "OverflowCounter.h" void OverflowCounter::HasOverflowed() { next_counter_.Count(); } void OverflowCounter::HasResetted() { next_counter_.Reset(); }
clock-4: g++ -std=c++14 *.cpp -o $@ run: clock-4 ./clock-4 clean: -rm -f *.o a.out core clock-4 zip: zip ../clock-4.zip *.txt *.cpp *.h
Apply "Non-Virtual Interface" Idiom -----------------------------------
To advance to the next step apply the following changes: * Add an interface `ICounter` to class `LimitCounter`, with the member functions `Count` and `Reset`. * in the interface these need to be pure `virtual` but * to keep with 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 { virtual ~ICounter() =delete; virtual void Count() =0; virtual void Reset() =0; }; // ---------------------------------- * Having `LimitCounter` implement that interface means as little as changing it like below. The current content can stay as it was unless you want to indicate which member functions implement some interface function (using `override`) and that your design follows 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 consructor argument type! ================================================================= Optional/Advanced Discuss based on the LSP – ie. 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: * Which classes can currently be used in place of which other classes (or interfacesa NOTE: The following question may be "theoretically" answereds based on the LSP only, but the MINIMAL way to IMPLEMENT it requires the use of private inheritance combined with virtual base classes, so its defintely NOT for beginners. * If `OverflowCounter` should only usable in place of `ICounter` but NOT in place or `LimitCounter`, with which changes could this be achieved?

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