[英]C++ inheritance of methods but wrong return types (automatic casting? typeid(*this) ?)
我有一个带有返回类对象的方法的 BaseClass,我有一个 DerivedClass。 现在,当我有一个 DerivedClass 对象并调用 BaseClass 中定义的方法时,返回值是 ob 类型 BaseClass,不幸的是不是 DerivedClass 类型。
class BaseClass {
public:
typeof(*this) myMethod1() {return *this;} // nice if that would work
BaseClass& myMethod2() {return *this;}
BaseClass myMethod3() {return BaseClass();}
};
class DerivedClass : public BaseClass {};
DerivedClass tmp;
tmp.myMethod1();
tmp.myMethod2();
tmp.myMethod3();
// all three methods should return an object of type DerivedClass,
// but really they return an object of type BaseClass
所以我希望实现的是使用超类的方法,但使用派生类的返回类型(自动转换?)。 myMethod1() 是我唯一能想到的,但它不起作用。
我已经搜索过,但没有找到任何令人满意的东西。
您想使用CRTP( http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern )模式:
template <class Derived>
class BaseClass {
public:
Derived *myMethod1() {return static_cast<Derived *>(this);}
Derived& myMethod2() {return static_cast<Derived&>(*this);}
};
class DerivedClass : public BaseClass<DerivedClass> {};
DerivedClass tmp;
tmp.myMethod1();
tmp.myMethod2();
只需使用协变返回类型规则,即可完成。
重述它:如果通过指针或引用返回,则覆盖可以显式地具有从基类中返回的类型派生的返回类型,并且它是有效的虚拟覆盖。
10.3虚函数§7
重写函数的返回类型应与重写函数的返回类型相同,或者与函数类的协变相同。 如果函数D :: f覆盖函数B :: f,则函数的返回类型如果满足以下条件则是协变的:
- 两者都是指向类的指针,都是对类的左值引用,或者两者都是对类112的右值引用
- 返回类型B :: f中的类与D :: f的返回类型中的类相同,或者是D类的返回类型中类的明确且可访问的直接或间接基类: :F
- 指针或引用都具有相同的cv限定,并且返回类型D :: f中的类类型具有与B :: f的返回类型中的类类型相同的cv-qualification或更少的cv-qualification。
如果您实际上不想将其设置为虚拟,则可以在派生类中定义函数并回调基类。
如果您有多个派生类,则可以考虑使用CRTP使其更快:
template <class X>
struct CRTP : BaseClass {
X& myMethod1() {return static_cast<X&>(*this;)} // covariant maybe-virtual
X& myMethod2() {return static_cast<X&>(*this;)} // covariant maybe-virtual
X myMethod3() {return X();} // Not virtual
};
struct DerivedClass1 : CRTP<DerivedClass1> {};
struct DerivedClass2 : CRTP<DerivedClass2> {};
struct DerivedClass3 : CRTP<DerivedClass3> {};
我不能评论你的回答,虽然这应该是评论而不是答案..但无论如何。 我首先要说我对此不太确定,但我认为您使用“从基础到派生”构造函数的解决方案有几个问题。
首先,如果您的 DerivedClass 中有任何不是 BaseClass 成员的成员,那么在DerivedClass(const BaseClass& src)
时,这些成员将被初始化为其默认值。 这通常不是问题,但是当您使用
DerivedClass someObject = ++someDerivedClassObject;
编译器可能将其称为:
DerivedClass someObject = DerivedClass(++((BaseClass)someDerivedObject));
其次,由于这是创建一个新对象,如果您将 DerivedClass 对象按引用或按地址传递给某个函数并期望产生副作用,则可能会得到意想不到的结果,因为++
创建了一个新对象。 但是,如果您有后缀增量( operator++(int)
),这可能正是您正在寻找的行为。
这个帖子中已经给出的答案是我自己推荐的。 不确定“您的基类已经是模板”是什么意思。
附注。 正如我所说,根据 Stack Overflow 的规则,这不是一个好的答案,但我刚刚创建了一个帐户,所以我无法评论其他人的答案.. 也许有人可以确认并移动这个?
谢谢你的回答。 也许我的问题不够明确,但我可以通过添加另一个构造函数来解决我自己的问题。
澄清一下:我的BaseClass有一个成员方法操作符+()和DerivedClass(没有那个成员方法)。 现在当我调用DerivedClass'运算符+()时,返回类型是BaseClass。 我可以简单地将运算符+()添加到DerivedClass,但是,添加接受超类型参数(此处为BaseClass)的Copy-Constructor解决了问题并且返回类型自动变为正确:
DerivedClass(const BaseClass& src) : BaseClass(src) {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.