考虑这个输出:
Current time: 6:30 pm
Current time: 18:30
Current time: evening.
Current time: evening (for many it is dinner time, but many eat dinner later).
请注意,最后两个有一个句号,而前两个没有。我使用以下代码中的System::displayCurrentTime
成员函数获得了所需的输出:
#include <iostream>
#include <string>
#include <memory>
class TimeDisplay {
public:
virtual std::string tell() const = 0;
virtual std::string tellMaybeWithPeriod() const = 0;
};
class ClockDisplay12Hours : public TimeDisplay { // #1
std::string tell() const override {return "6:30 pm";}
std::string tellMaybeWithPeriod() const override {return tell();}
};
class ClockDisplay24Hours : public TimeDisplay { // #2
std::string tell() const override {return "18:30";}
std::string tellMaybeWithPeriod() const override {return tell();}
};
class DescriptiveTimeDisplay : public TimeDisplay { // #3
std::string tell() const override {return "evening";}
std::string tellMaybeWithPeriod() const override {return tell() + ".";}
};
class CrazyDescriptiveTimeDisplay : public TimeDisplay { // #4
std::string tell() const override {return "evening (for many it is dinner time, but many eat dinner later)";}
std::string tellMaybeWithPeriod() const override {return tell() + ".";}
};
struct System {
static std::shared_ptr<TimeDisplay> timeDisplay;
static std::string timeAsString() {return timeDisplay->tell();}
static std::string timeAsStringMaybeWithPeriod() {return timeDisplay->tellMaybeWithPeriod();}
// #3 and #4 will have a period, the others will not.
static void displayCurrentTime (std::shared_ptr<TimeDisplay> t) {
timeDisplay = t;
std::cout << "Current time: " << System::timeAsStringMaybeWithPeriod() << '\n';
}
static void foo (std::shared_ptr<TimeDisplay>) {} // #1 and #3 will have a period, the others will not.
static void bar (std::shared_ptr<TimeDisplay>) {} // #1, #2, and #4 will have a period, the others will not.
static void baz (std::shared_ptr<TimeDisplay>) {} // #2 will have a period, the others will not
};
std::shared_ptr<TimeDisplay> System::timeDisplay;
int main() {
const std::shared_ptr<TimeDisplay> clocks[] = {std::make_shared<ClockDisplay12Hours>(), std::make_shared<ClockDisplay24Hours>(),
std::make_shared<DescriptiveTimeDisplay>(), std::make_shared<CrazyDescriptiveTimeDisplay>()};
for (std::shared_ptr<TimeDisplay> t : clocks)
System::displayCurrentTime(t);
}
这不是非常混乱,但请注意,实现foo
,bar
,baz
的下一个功能需要具有TimeDisplay
的不同派生类的句点,以及实际上有超过4个这样的派生类,还有3个以上的新成员函数需要处理。是否有一种更清晰,更优雅的方式来处理这些即将到来的成员函数,而不是为每个foo
,bar
,baz
等编写新的虚函数...期间哪个不会?以某种方式使用模板(例如重命名派生类Derived<0>
,Derived<1>
等......然后使用这些编译时整数来满足上述注释中规定的规则)?也许避免模板并做其他事情?
答案 0 :(得分:1)
可以通过为四个时钟显示类提供bool模板参数来完成。 e.g。
template <bool P>
class DescriptiveTimeDisplay : public TimeDisplay { // #3
std::string tell() const override { return "evening"; }
std::string tellMaybeWithPeriod() const override { return tell() + (P ? "." : ""); }
};
并控制是否通过将类作为实例来显示句点,例如
std::make_shared<DescriptiveTimeDisplay<true>>()
对于displayCurrentTime
,foo
,bar
,baz
这四个函数中的每一个,您可以通过实例化四个TimeDisplay
子类来控制它们的显示格式使用不同的bool模板参数。