简体   繁体   English

从C ++中的基类返回派生的“ this”的多态性

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

相关问题 C ++多态性访问基类的派生类字段 - C++ polymorphism access derived class fields from base class C ++静态多态性–引用专业模板方法,这些方法从基类指针的派生类中重载 - C++ Static Polymorphism––Referencing Specialized Template Methods Overloaded In Derived Class From Base Class Pointer C++ 多态性:是否可以将 function 从双派生 class 使用到基础 ZA2F2ED4F8EBC2ABC1DZC20? - C++ Polymorphism : Is it possible to use a function from a double derived class into the base class? C ++多态:如何测试一个类派生自另一个基类? - C++ polymorphism: how to test if a class derived from another base class? C ++多态性将派生类设置为基类对象 - C++ Polymorphism setting derived classes to base class object 多态C ++,尝试访问从抽象基类派生的类的成员函数 - polymorphism c++, trying to access member functions of classes that are derived from abstract base class C++ Expand class Base with class Derived that contains a function returning a * b from base class - C++ Expand class Base with class Derived that contains a function returning a * b from base class C ++多态性:派生类调用基类虚拟函数,而不是重写的派生类 - C++ Polymorphism: Derived class calls Base class virtual funciton instead of the overriden derived one 从基类派生类扩展多态性 - Extending polymorphism in derived class from base class 在派生类 C++ 中使用 from base - Using from base in derived class C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM