C++ 继承返回*this的成员函数
为什么C++ 继承返回*this的成员函数,c++,inheritance,this,C++,Inheritance,This,为什么派生类的*此仍然是基本类型 我以为typename X会解决这个问题 如果这看起来很难看,有什么更好的办法 失败的尝试: template <typename T> class Derived; template <typename T, typename X> class Base{ public: T val; X f(void){ return *this; } }; temp
派生类的*此
仍然是基本
类型
我以为typename X
会解决这个问题
如果这看起来很难看,有什么更好的办法
失败的尝试:
template <typename T>
class Derived;
template <typename T, typename X>
class Base{
public:
T val;
X f(void){
return *this;
}
};
template <typename T>
class Derived: public Base<T, Derived<T> >{
};
int main(void){
Derived<int> B;
Derived<int> C = B.f();
}
模板
类派生;
模板
阶级基础{
公众:
T值;
X f(无效){
归还*这个;
}
};
模板
派生类:公共基{
};
内部主(空){
衍生B;
导出C=B.f();
}
错误:
test4.cpp(9): error: no suitable user-defined conversion from "Base<int, Derived<int>>" to "Derived<int>" exists
return *this;
^
detected during instantiation of "X Base<T, X>::f() [with T=int, X=Derived<int>]" at line 20
compilation aborted for test4.cpp (code 2)
test4.cpp(9):错误:不存在从“基本”到“派生”的合适的用户定义转换
归还*这个;
^
在第20行实例化“X Base::f()[with T=int,X=Derived]”时检测到
test4.cpp的编译中止(代码2)
您可以通过以下方式进行向下广播:
X f(){ return static_cast<X&>(*this);}
xf(){return static_cast(*this);}
您可以通过以下方式进行向下广播:
X f(){ return static_cast<X&>(*this);}
xf(){return static_cast(*this);}
您有
X f(void){
return *this;
}
在此函数中,*this
的类型仍然是基类类型。没有从基类型到X
的自动转换
我无法建议一个干净的解决方案,因为X
在这一点上可以是任何东西,而不一定是派生的
我可以使用:
template <typename T>
class Derived2 : public Base<T, double>
{
};
然后,您可以使用:
X& f(void){
return static_cast<X&>(*this);
}
X&f(无效){
返回静态_cast(*此);
}
请注意,我将返回类型从X
更改为X&
。它避免了每次调用函数时制作副本的成本。
X f(void){
return *this;
}
在此函数中,*this
的类型仍然是基类类型。没有从基类型到X
的自动转换
我无法建议一个干净的解决方案,因为X
在这一点上可以是任何东西,而不一定是派生的
我可以使用:
template <typename T>
class Derived2 : public Base<T, double>
{
};
然后,您可以使用:
X& f(void){
return static_cast<X&>(*this);
}
X&f(无效){
返回静态_cast(*此);
}
请注意,我将返回类型从X
更改为X&
。它避免了每次调用函数时制作副本的成本。当编译器查看类基时,它没有理由相信实际上存在继承自它的派生的。可以执行class Other:public Base{}
,并且从class Base
到Derived
的转换将不正确,因此不允许自动转换
如果您制定了一条规则,规定第二个模板参数必须是继承该基的派生类型(这违反了class Other
),则可以通过强制转换绕过类型系统,但是要确保没有违反规则。当编译器查看类库时,没有理由相信实际上有一个继承自它的派生的。可以执行class Other:public Base{}
,并且从class Base
到Derived
的转换将不正确,因此不允许自动转换
如果您制定了一个规则,规定第二个模板参数必须是继承该基的派生类型(这是class Other
违反的),那么您可以通过强制转换绕过类型系统,但确保不违反该规则。首先,我将修改base
,使其只接受一个模板参数。
这样,它与CRTP习语的常见形式完全匹配。
实际上,在我看来,没有理由在这种情况下同时使用T
和Derived
作为模板参数,因为后者已经包含了前者和T,Derived
是您想要遵循的模式:
template<typename>
class Base;
template <typename T, template<typename> typename X>
class Base<X<T>> {
// ...
};
template <typename T>
class Derived: public Base<Derived<T>>{
// ....
};
模板
阶级基础;
模板
阶级基础{
// ...
};
模板
派生类:公共基{
// ....
};
然后您可以从底部使用@Jarod42提到的促销:
X<T> f(void) {
return *static_cast<X<T>*>(this);
}
xf(无效){
返回*static_cast(此);
}
请注意,这里您正在系统地制作对象的副本,可能它不是您想要的
另一个选项是稍微修改架构并使用协变返回类型(它遵循一个最小的工作示例):
模板
阶级基础{
T值;
公众:
虚常数基&f(void)常数{
归还*这个;
}
};
模板
派生类:公共基{
公众:
虚常量派生&f(void)常量{
归还*这个;
}
};
内部主(空){
衍生B;
派生C=B.f();
}
哪个更适合您主要取决于实际问题。首先,我将修改Base
,使其只接受一个模板参数。
这样,它与CRTP习语的常见形式完全匹配。
实际上,在我看来,没有理由在这种情况下同时使用T
和Derived
作为模板参数,因为后者已经包含了前者和T,Derived
是您想要遵循的模式:
template<typename>
class Base;
template <typename T, template<typename> typename X>
class Base<X<T>> {
// ...
};
template <typename T>
class Derived: public Base<Derived<T>>{
// ....
};
模板
阶级基础;
模板
阶级基础{
// ...
};
模板
派生类:公共基{
// ....
};
然后您可以从底部使用@Jarod42提到的促销:
X<T> f(void) {
return *static_cast<X<T>*>(this);
}
xf(无效){
返回*static_cast(此);
}
请注意,这里您正在系统地制作对象的副本,可能它不是您想要的
另一个选项是稍微修改架构并使用协变返回类型(它遵循一个最小的工作示例):
模板
阶级基础{
T值;
公众:
虚常数基&f(void)常数{
归还*这个;
}
};
模板
派生类:公共基{
公众:
虚常量派生&f(void)常量{
归还*这个;
}
};
内部主(空){
衍生B;
派生C=B.f();
}
哪个更适合你主要取决于实际问题。f
是的成员函数