C ++中的多态性有些麻烦。我正在尝试为初始化类创建一种相当奇怪的语法,但是当我从基类方法返回“ this”时,似乎丢失了新创建的派生类。

在下面的伪代码中,我需要让Base :: initWithPuppies()能够执行一些默认操作并返回其从中调用的派生类。

我想要这样的语法:

Bar *baz = (new Bar)->initWithPuppies();


最好不要使用模板,并且需要强制转换为:

initWithPuppies<Bar *>();


是的,我知道那很古怪。但这是有原因的,“最佳做法”在这种情况下不适用。认为这只是“假设”。我知道您可能应该:

Bar *baz = new Bar;
baz->initWithPuppies();


但是我需要前一种语法。

伪代码:

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();


编辑:

如果可以通过某种方式使用此语法:

Bar *baz = (Bar::create())->initWithPuppies();


那会更好,但是我不知道如何在基类中创建create而不进行类型转换的派生新实例:

Bar *baz = (Bar::create<Bar *>())->initWithPuppies();


我的答案:(我自己无法回答8个小时)

尽管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();

最佳答案

我想要这样的语法:


Bar *baz = (new Bar)->initWithPuppies();


好,就在那儿停下来那不是您想要的语法。构造函数存在于C ++中是有充分的理由的,除非有充分的理由绕过它们,否则应使用它们。

如果由于某种原因不能使用构造函数,请使用工厂函数:

Bar *baz = Bar::initWithPuppies();


它将完成对象的分配和初始化,因此您不必直接使用new

至于错误的原因,是因为您不能隐式上变频。从继承的性质来看,所有Bar对象也是Base对象。因此,C ++将隐式将指向派生类的指针转换为指向基类的指针。反之则不成立:Base类并非自动成为所有Bar类。因此,C ++为尝试向上转换继承层次结构将正确地给您一个错误。

您必须显式使用dynamic_cast进行这种转换。您可以使用C样式的强制转换或static_cast,但是只有当您完全确定类型是您期望的类型时,它们才起作用。

关于c++ - 从C++中的基类返回派生的“this”的多态性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7341975/

10-09 00:47
查看更多