Почему возврат виртуального класса * по значению * в C ++ изменяет v-таблицу? - PullRequest
0 голосов
/ 06 августа 2020

В следующем коде я возвращаю производный класс CDerived по значению из функции, возвращающей его базовый класс, CBase.

Например, CDerived содержит поле _number, и я понимаю, что оно «отрезано» во время преобразования в тип возвращаемого значения по значению, CBase.

Однако меня смущает то, что виртуальная функция Print каким-то образом превращается в свою версию базового класса. В этом случае v-таблица не была просто нарезана, она была изменена.

В моем фактическом коде _number не существует, как и других данных. Я хотел бы иметь возможность возвращать производный класс только для его v-таблицы, которая объявлена ​​базой.

From this question Я вижу, что могу «обойти» это конкретная проблема, возвращая указатель функции (или я полагаю, что создаю свою собственную v-таблицу), но почему именно v-таблица изменяется в первую очередь, и есть ли способ обойти это изменение? .

#include <iostream>

class CBase
{
public:
    virtual void Print() { std::cout << "CBase" << std::endl; }
};

class CDerived : public CBase
{
    int _number;

public:
    explicit CDerived(int n) : _number(n) { }
    virtual void Print() override { std::cout << "CDerived" << std::endl; }
};

CBase GetBase()
{
    return CDerived(42);
}

int main()
{
    CBase base = GetBase();
    base.Print(); // Outputs CBase
    return 0;
}

1 Ответ

2 голосов
/ 06 августа 2020

Вот как работает C ++.

Вы не возвращаете объект CDerived, вы возвращаете CBase, скопированный из подобъекта CBase временного CDerived.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...