我希望函数返回其真实类型,即使它在子类中调用。这是测试代码:
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){};
};
int main()
{
Sub().getSelf().testSuper();//OK
//Sub().getSelf().testSub();//Error
return 0;
}
在Objective-C中,我可以使用instanttype
来解决这个问题
但是在C ++中,有可能吗?
顺便说一下,我不想要template
实现,因为它可能会增加代码大小。
答案 0 :(得分:3)
但是在C ++中,有可能吗?
是的,就像C ++中的任何内容一样,有很多方法可以做到。但这两种方式都要求您在struct Super {
auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
类中添加内容。
如果您不需要虚函数,则只需覆盖(静态)该函数:
template<typename Subclass>
struct AddGetSelf {
auto getSelf() -> Subclass& {
return static_cast<Subclass&>(*this);
}
};
当然,如果您不喜欢复制粘贴该代码,您可以随时创建一个mixin类(CRTP模板):
struct Super : AddGetSelf<Super> {
using AddGetSelf<Super>::getSelf;
void testSuper(){};
};
struct Sub : Super, AddGetSelf<Sub> {
using AddGetSelf<Sub>::getSelf;
void testSub(){};
};
您可以在类中使用mixin:
struct Super {
virtual auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& override {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
如果您需要虚拟多态,则可以依赖协变返回类型:
vendor/assets/javascripts
以下是Coliru
的实例如果您担心二进制大小,请考虑静态链接和链接时间优化。
我建议你尝试两种解决方案并比较二进制大小,因为模板大小的增加可以通过编译器优化来消除,虚拟多态可以阻止编译器进行这些优化。
答案 1 :(得分:1)
我将继续否。在c ++中没有方便的机制来执行你想要的。 (方便的意思是避免使用任何样板,Guillaume在answer中提出的IMO选项当然值得探讨。)
必须复制不同案例的代码。在运行时期间无法创建类型和对象,例如在C#中。所以你必须为每种类型都有代码。
你可以通过静态多态来做你想做的事,尽管那些是模板。也许编译器足够聪明,可以优化getSelf
的每个副本,毕竟它们都返回相同的指针。但是从语言的角度来看,你必须为每种类型提供一个定义。
有运行时类型信息,但您仍然需要在类型之间if
有效地复制代码。
您可以使用RTTI和动态强制转换来实现您的示例纯运行时,但它会有点难看,因为您必须手动转换为引用...而且很危险。
E.g:
#include <iostream>
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){std::cout << "test\n"; };
};
int main()
{
Sub().getSelf().testSuper();//OK
dynamic_cast<Sub&>(Sub().getSelf()).testSub();//Danger
return 0;
}
答案 2 :(得分:1)
但是在C ++中,有可能吗?
简短回答是 - 不直接,因为它发生在C#中。
this
的类型是指向提供成员函数定义的子对象类型的指针。
也就是说,Super *
中的getSelf
定义中的Super
,Sub *
中getSelf
定义中Sub
内的Sub().getSelf().method();
。
那就是说,请注意双重调度的目标符合您的要求
缺点是在这种情况下不再可能像struct Visitor;
struct Super
{
virtual void getSelf(Visitor &) = 0;
void testSuper(){}
};
struct Sub : Super
{
void getSelf(Visitor &) override;
void testSub(){}
};
struct Visitor
{
void accept(Sub &sub)
{
sub.testSuper();
sub.testSub();
}
};
void Sub::getSelf(Visitor &v)
{
v.accept(*this);
}
int main()
{
Visitor visitor;
Sub sub;
Super &super = sub;
super.getSelf(visitor);
}
这样的调用
它遵循一个最小的工作示例:
return response($content)
->withHeaders([
'Content-Type' => 'text/xml'
]);
答案 3 :(得分:1)
在C ++中,无法在Object-C中完成所需的操作。他们有不同的对象调用模型。见https://github.com/ampproject/amphtml/blob/master/ads/google/csa.md。当您在C ++中调用object时,编译器必须在编译时了解有关成员函数的所有内容。在Object-C中,您不直接调用成员函数,而是向对象发送消息。所以这是运行时绑定。