繁体   English   中英

C++ 继承方法但返回类型错误(自动转换?typeid(*this) ?)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM