我有两个’接口’类:AbstractAccess和AbstractPrint,以及从它们继承并使用它们的方法的AbstractRun类。另外,我有两个接口实现:Accessor for …
虽然你已经解决了你的问题,但我还是深入研究了这个问题,并且我想解决一些关于继承问题的困惑。
当您的类与另一个类具有“是”关系时,将使用继承。派生类应该是您继承的类的替代。
在你的情况下,你可以放心地说 class Print 是一个 class AbstractPrint 和 class Access 同样的 class AbstractPrint 因此继承在这里很好。
class Print
class AbstractPrint
class Access
另一方面, class AbstractRun 是 不 一个 AbstractPrint 而且都不是 AbstractAccess 。 AbstractRun 简单地处理/组合一个 AbstractPrint 和 AbstractAccess 。这种关系应该用聚合(或组合)抽象出来 AbstractRun 具有 指向a的引用/指针 AbstractRun 和a AbstractPrint 。这会 AbstractRun 具体,所以我们将其重命名为 Runner 。
class AbstractRun
AbstractPrint
AbstractAccess
AbstractRun
Runner
class Runner { public: // We now need a constructor to set the references. Runner(AbstractAccess& access, AbstractPrint& print) : accessor(access), printer(print) {} void run (void) { printer.print(accessor.access()); } private: AbstractAccess& accessor; // has a AbstractAccess AbstractPrint& printer; // has a AbstractPrint };
现在 Access 和 Print 可以像以前一样定义。
Access
Print
但是我们也要改进它们:
class Print: public virtual AbstractPrint { public: void print (string s) { cout << s << endl; } };
我们不 需要 虚拟继承。虚拟继承用于解决钻石问题。但是没有钻石比AbstractRunner成为一个具体的类。所以让我们删除不必要的限定符。
class Accessor : public AbstractAccess { public: string access (void){ return name; } void setName(string name) { this->name = name; } private: string name; }; class Print: public AbstractPrint { public: void print (string s) { cout << s << endl; } };
此外,如果你有一个C ++ 11兼容的编译器,我建议你添加 override 覆盖基本函数的方法的限定符,以便能够对从基类中获取的方法进行去编程。
override
class Accessor : public AbstractAccess { public: string access (void) override { //overrides AbstractAcces method return name; } void setName(string name) { //does not override. is a method at Accessor level this->name = name; } private: string name; };
现在初始化时 Runner ,我们需要通过具体的访问器和打印机。这可以这样做:
// Somewhere in a .cpp - file Accessor accessor; Print printer; Runner runner(accessor, printe); runner.run(); //will call printer and accessor through the references.