Как инициализировать ссылку C ++ с различными конструкторами на основе условия? - PullRequest
1 голос
/ 28 марта 2019

Ссылочная переменная foo ниже инициализируется либо экземпляром Foo, либо его производным классом Bar на основе condition. Как ни странно, основываясь на результатах метода say(), foo представляется экземпляром Foo, а не экземпляром Bar - почему?

#include <iostream>

class Foo {
public:
    virtual void say() const {
        std::cout << "Foo\n";
    }
};

class Bar : public Foo {
public:
    virtual void say() const {
        std::cout << "Bar\n";
    }
};

int main() {
    constexpr bool condition = false;
    const Foo& foo = condition ? Foo() : Bar();
    foo.say();   // outputs "Foo” ???                                                                                                  
    return 0;
}

Если я аннотирую каждый конструктор, я вижу, что конструктор Bar вызывается при вычислении троичного выражения. Если я аннотирую каждый деструктор, я вижу, что деструктор Bar вызывается до инициализации foo - это говорит мне, что временный объект Bar создается троичным оператором, но уничтожается до инициализации - почему?

Скомпилировано с (Apple LLVM версия 9.0.0 (clang-900.0.39.2))

clang++ -Wall -std=c++11 foo.cpp -o foo

1 Ответ

5 голосов
/ 28 марта 2019

Проблема с

const Foo& foo = condition ? Foo() : Bar();

заключается в том, что обе части должны возвращать один и тот же тип.Поскольку Foo() и Bar() не являются одинаковыми типами, компилятор пытается преобразовать их.Единственное действительное преобразование, которое он может сделать, это нарезать Bar() на его Foo часть.Это означает, что независимо от того, что вы получите, вы будете привязывать ссылку к Foo, а часть Bar исчезнет.

Чтобы исправить это, вам нужно использовать указатели, такие как

#include <iostream>
#include <memory>

class Foo {
public:
    virtual ~Foo() = default;  // don't forget to add this when using polymorphism
    virtual void say() const {
        std::cout << "Foo\n";
    }
};

class Bar : public Foo {
public:
    virtual void say() const {
        std::cout << "Bar\n";
    }
};

int main() {
    constexpr bool condition = false;
    auto foo = condition ? std::make_unique<Foo>() : std::make_unique<Bar>();
    foo->say();   // outputs "Bar" now                                                                                                  
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...