如何继承成员函数,使其始终返回对派生实例的引用
How to inherit a member function so that it always returns a reference to the derived instance?
我正在研究一个迭代器家族,其中所有的迭代器类X
都有共同的X& operator++() {++x; return *this}
,因此将其放在一个公共基类中似乎是一个好主意。不幸的是,返回类型改变了,因为它应该总是返回对派生类的引用。
下面说明了这个问题。我希望f()
工作,但我能想出的唯一解决办法是g()
和h()
,这是不令人满意的:
struct A {
A& f() {return *this;}
template <typename T>
T& g() {return *(T*)this;}
template <typename T>
T& h(T& unused) {return *(T*)this;}
};
struct B : A {
int x;
B(int x) : x(x) {}
};
int main() {
B b(12);
//B b1 = b.f(); // error: conversion from 'A' to non-scalar type 'B' requested
B b2 = b.g<B>(); // works
B b3 = b.h(b); // works
}
是否有办法使B b1 = b.f();
工作?也许使用c++ 11的特性?
使用CRTP:
template<class Derived>
struct A {
Derived& f() {return static_cast<Derived&>(*this);}
};
struct B : A<B> {
int x;
B(int x) : x(x) {}
};
F可以返回A,所以你不能将结构体A存储在结构体b中,但是你可以用指针做相反的事情。
struct A {
A& f() {return *this;}
template <typename T>
T& g() {return *(T*)this;}
template <typename T>
T& h(T& unused) {return *((T *)this);}
};
struct B : A {
int x;
B(int x) : x(x) {}
B(const B & other) : x(other.x) {}
};
int main() {
A *b = new B(12);
A *b1 = new B( (const B&)b->f());
B b2 = b->g<B>();
A b3 = B->h(*b);
}
@ecatmur的答案解决了指定的问题,但不幸的是,CRTP不会比这更进一步。考虑有两层继承的情况:
template <typename D>
struct A {
D& f() {return *static_cast<D*>(this);}
};
template <typename D>
struct B : A<D> {
int x;
B(int x=0) : x(x) {}
};
struct C : B<C> {
double y;
C(double y=0.) : y(y) {}
};
int main() {
C c(12.5);
C c1 = c.f(); // works
}
如果只需要实例化C
,这可以正常工作,但现在似乎完全不可能实例化B
:
int main() {
B<B> b; // error: type/value mismatch at argument 1 in template parameter list
}
我尝试了一堆变化,包括typename
和template
关键字,但没有成功地获得B
的实例。也不能使用递归默认模板实参:
template <typename D=B> struct B : A<D> {}; // error
因此,CRTP似乎只在单继承情况下是一个好主意。
我最终用简单的解决方案来返回对基类A&
的引用。由于这种方式不会丢失信息,派生类总是可以将返回的引用强制转换为派生类型:
struct A {
A& f() {return *this;}
};
struct B : A {
int x;
B(int x=0) : x(x) {}
};
struct C : B {
double y;
C(double y=0.) : y(y) {}
};
int main() {
B b(12);
B b1 = (B&)b.f(); // works
C c(12.5);
C c1 = (C&)c.f(); // works
}
因此,似乎正确的方法是只返回基类引用,并在必要时在派生类中强制转换。
相关文章:
- 返回派生类型时出现协变类型错误
- C++ 基类调用但返回派生类
- typeid.name 返回派生类类型之前的数字
- 无法返回派生类型的标准::unique_ptr<>
- 如何在不转换回基类类型的情况下返回派生类型的对象?
- 从虚拟方法返回派生对象作为基础
- 不能返回派生的类(无法转换)
- 使用动态铸件来返回派生类内部的变量的不同值
- 如何返回派生类型
- 继承的函数返回派生类,而不是基类
- 从基类成员函数返回派生类的实例
- 如何重写 QObject::findChildren 以仅返回派生类型
- 从基类型的函数返回派生类对象
- 基类方法返回派生类 objec
- 重写虚拟方法时无法返回派生类指针
- 具有基类向量的类的下标运算符重载,该向量必须返回派生类
- 从指向基类型的指针向量,返回派生类型的第一个元素,该元素被强制转换为派生类型
- 返回派生类类型的基类中的方法
- 在基类和派生类上操作时如何返回派生类型
- 通过抽象基类的指针返回派生类对象