[英]Polymorphism returning “this” of derived, from base class in C++
Having some trouble with polymorphism in C++. C ++中的多态性有些麻烦。 I'm trying to create a rather strange syntax for initializing a class but it appears I'm losing the newly created derived class when I return "this" from a base class method.
我正在尝试为初始化类创建一种相当奇怪的语法,但是当我从基类方法返回“ this”时,似乎丢失了新创建的派生类。
In the pseudo code below, I need to have Base::initWithPuppies() able to do some default action and return the derived class that it is calling from. 在下面的伪代码中,我需要让Base :: initWithPuppies()能够执行一些默认操作并返回其从中调用的派生类。
I want to have this syntax: 我想要这样的语法:
Bar *baz = (new Bar)->initWithPuppies();
Preferably without using templates and needing to cast like: 最好不要使用模板,并且需要强制转换为:
initWithPuppies<Bar *>();
Yeah, I know it's rather wack. 是的,我知道那很古怪。 But there's a reason for it and "best practices" is not applying in this situation.
但这是有原因的,“最佳做法”在这种情况下不适用。 Consider this just a "what if".
认为这只是“假设”。 I know you should probably:
我知道您可能应该:
Bar *baz = new Bar;
baz->initWithPuppies();
But I need the former syntax. 但是我需要前一种语法。
Pseudo code: 伪代码:
class Base
{
// Kittens
};
class Foo : public Base
{
public:
Base * initWithPuppies();
virtual void test() = 0;
};
Base * Foo::initWithPuppies()
{
// Call to derived works
this->test();
return this;
}
class Bar : public Foo
{
public:
void test();
};
void Bar::test()
{
std::cout << "It Works!" << std::endl;
}
// Preferred syntax
// This gives "cannot convert from 'Base *' to 'Bar *' "
Bar *baz = (new Bar)->initWithPuppies();
baz->test();
/*------------------------------------------*/
// This gives " 'test' : is not a member of 'Base' "
Base *baz = (new Bar)->initWithPuppies();
baz->test();
/*------------------------------------------*/
// This gives "Base is not a polymorphic type"
UIBar *man = dynamic_cast<UIBar *>((new UIBar)->initWithFrame());
baz->test();
EDIT: 编辑:
If it was somehow possible to have this syntax: 如果可以通过某种方式使用此语法:
Bar *baz = (Bar::create())->initWithPuppies();
That would be even better, but I couldn't figure out how to have create in the base class create a new instance of a derived without typecasting: 那会更好,但是我不知道如何在基类中创建create而不进行类型转换的派生新实例:
Bar *baz = (Bar::create<Bar *>())->initWithPuppies();
MY ANSWER: (can't answer my own for 8 hours) 我的答案:(我自己无法回答8个小时)
Although Nicol Bolas is correct and as I stated the syntax I want to use is bad practice, if you really do need to use a similar syntax as I do (don't ask...) then you can do this: 尽管Nicol Bolas是正确的,并且正如我所说的,我想使用的语法是不好的做法,但是如果您确实确实需要使用与我相似的语法(不要问...),则可以执行以下操作:
class Base
{
// Kittens
};
class Foo : public Base
{
public:
virtual void test() = 0;
private:
void _initWithPuppies();
};
void Foo::initWithPuppies()
{
// Do shit
}
class Bar : public Foo
{
public:
Bar * initWithPuppies();
void test();
};
Bar * Bar::initWithPuppies()
{
this->_initWithPuppies();
return this;
}
void Bar::test()
{
std::cout << "It Works!" << std::endl;
}
Bar *baz = (new Bar)->initWithPuppies();
baz->test();
I want to have this syntax:
我想要这样的语法:
Bar *baz = (new Bar)->initWithPuppies();
OK, stop right there. 好,就在那 That is not the syntax you want.
那不是您想要的语法。 Constructors exist in C++ for a good reason, and unless you have a very good reason for circumventing them, you should use them.
构造函数存在于C ++中是有充分的理由的,除非有充分的理由绕过它们,否则应使用它们。
If you can't use a constructor for some reason, then use a factory function: 如果由于某种原因不能使用构造函数,请使用工厂函数:
Bar *baz = Bar::initWithPuppies();
It will do the allocation and initialization of the object, so you don't have to use new
directly. 它将完成对象的分配和初始化,因此您不必直接使用
new
。
As to the reason for the error, it is because you cannot implicitly up-convert. 至于错误的原因,是因为您不能隐式上变频。 All
Bar
objects are also Base
objects, by the nature of inheritance. 根据继承的性质,所有
Bar
对象也是Base
对象。 Therefore, C++ will implicitly convert pointers to a derived class into pointers to a base class. 因此,C ++将隐式将指向派生类的指针转换为指向基类的指针。 The reverse is not true:
Base
classes are not automatically all Bar
classes. 反之则不成立:
Base
类并非自动成为所有Bar
类。 Therefore, C++ will rightfully give you an error for attempting to convert up the inheritance hierarchy. 因此,C ++为尝试向上转换继承层次结构将正确地给您一个错误。
You have to explicitly use a dynamic_cast
to do this kind of conversion. 您必须显式使用
dynamic_cast
进行这种转换。 You could use a C-style cast or a static_cast
, but those will only work if you're absolutely certain that the type is what you expect it to be. 您可以使用C风格的
static_cast
类型转换或static_cast
,但是只有在您完全确定类型就是您期望的类型时,它们才起作用。
Something you may find useful is C++'s support for covariant return types . 您可能会发现有用的是C ++对协变返回类型的支持。 This means that if in a base class you define a function that returns an object of type
Base *
, you can override that method to have it return either a Base*
or any pointer to a derived class of Base
. 这意味着,如果在基类中定义了一个返回
Base *
类型的对象的函数,则可以重写该方法以使其返回Base*
或指向Base
派生类的任何指针。 For example, this code is perfectly legal: 例如,此代码完全合法:
class Base {
public:
virtual ~Base() {} // Polymorphic classes need virtual destructors!
virtual Base* initWithPuppies() = 0;
}
class Derived: public Base {
public:
/* Note that the return type is Derived*, but it's still an override! */
virtual Derived* initWithPuppies() {
return this;
}
}
/* Perfectly legal code; Derived::initWithPuppies() returns a Derived* */
Derived* d = (new Derived)->initWithPuppies();
Hope this helps! 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.