c++ - 从 C++ 中的基类返回派生的 "this"的多态性

标签 c++ class inheritance casting polymorphism

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

那会更好,但我无法弄清楚如何在基类中创建一个没有类型转换的派生类的新实例:

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

最佳答案

I want to have this syntax:

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/

相关文章:

c++ - 类/结构函数是否存储在对象中?

c++ - std::ref 在此函数中有什么用?

C++ char 数组转 int 和 int 转 char 数组

c++ - 子类调用父成员而不是它自己的成员

java - 如何连接两个不同的类

具有继承模板的C++调用函数

c++ - 在分配给 double 变量后检索字符串 “0.1”

javascript - 如何从另一个类调用 javascript 类并在数组中推送(追加)值?

C# 结构 - 从外部库访问类

php - Wordpress:使用数组手动将类添加到 post_class?