Zee*_*bit 10 c++ oop inheritance abstract-class
在类层次结构的设计中,我使用了一个抽象基类,它声明了派生类将实现的各种方法.从某种意义上说,基类与C++中的接口一样接近.但是,有一个具体问题.考虑下面的代码声明我们的接口类:
class Interface {
public:
virtual Interface method() = 0;
};
class Implementation : public Interface {
public:
virtual Implementation method() { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
当然,这不会编译,因为你不能在C++中返回一个抽象类.为了解决这个问题,我使用以下解决方案:
template <class T>
class Interface {
public:
virtual T method() = 0;
};
class Implementation : public Interface<Implementation> {
public:
virtual Implementation method() { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
这个解决方案很有效,但是,对我来说,它看起来并不优雅,因为文本的冗余位将是接口的参数.如果你们能指出我们在设计方面的任何其他技术问题,我会很高兴,但这是我唯一关心的问题.
有没有办法摆脱冗余模板参数?可能使用宏?
注意:有问题的方法必须返回一个实例.我知道如果method()返回指针或引用,就没有问题.
Interface::method()Interface不使用指针或引用就无法返回实例.返回非指针,非引用Interface实例需要实例化Interface自身的实例,这是非法的,因为它Interface是抽象的.如果希望基类返回对象实例,则必须使用以下方法之一:
指针:
class Interface
{
public:
virtual Interface* method() = 0;
};
class Implementation : public Interface
{
public:
virtual Interface* method() { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
参考:
class Interface
{
public:
virtual Interface& method() = 0;
};
class Implementation : public Interface
{
public:
virtual Interface& method() { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
模板参数:
template<type T>
class Interface
{
public:
virtual T method() = 0;
};
class Implementation : public Interface<Implementation>
{
public:
virtual Implementation method() { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
虽然由于显而易见的原因无法按值返回,但返回指针或引用完全可以 - 这称为"协变返回类型",它是虚函数覆盖的有效形式:
struct Base { virtual Base * foo(); }
struct Derived : Base { virtual Derived * foo(); }
Run Code Online (Sandbox Code Playgroud)
关键是这Derived::foo()是一个真正的覆盖,而不是基础隐藏重载,因为Derived*is是指向派生类的指针Base.这同样适用于参考文献.
换句话说,如果你有一个Base * p,并且你打电话p->foo(),你总是可以将结果视为指向Base(但如果你有其他信息,例如你的类实际上是Derived,那么你可以使用该信息).
相反的组合顺序,即"逆变参数类型",不允许作为C++的一部分.