Виртуальное наследование и возврат объекта
От: _NN_ www.nemerleweb.com
Дата: 11.11.19 21:56
Оценка:
Имеем иерархию классов. Base <|- Derived <|- FinalClass <|- FinalClassEx
Почему при виртуальном наследовании Derived от Base нельзя возвратить объект из функции, а без него можно ?

class Base
{
public:
    explicit Base(char const*) {}
    Base() {}

    Base(const Base&) = delete;
    Base& operator=(const Base&) = delete;
};


class Derived : virtual public Base // Compiles without virtual
{
public:
    Derived() {}
    Derived(Derived&&) {}

    Derived& operator=(Derived&&) { return *this; }
    Derived(const Derived&) = delete;
    Derived& operator=(const Derived&) = delete;
};

class FinalClass  : public Derived
{   
public:
    FinalClass() {}
    FinalClass(FinalClass&&) {}

    FinalClass& operator=(FinalClass&&) { return *this; }
    FinalClass(const FinalClass&) = delete;
    FinalClass& operator=(const FinalClass&) = delete;
};


FinalClass f1()
{
    FinalClass f;
    return f;
}


class FinalClassEx : public FinalClass
{
public:
using FinalClass::FinalClass;
};

FinalClassEx f2()
{
    FinalClassEx f;
    return f;
}

int main()
{
    auto v1 = f1();
    auto v2 = f2();

    return 0;
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Виртуальное наследование и возврат объекта
От: reversecode google
Дата: 11.11.19 22:27
Оценка:
root@ubuntu64:~# c++ t.cpp -std=c++17
t.cpp: In function ‘FinalClassEx f2()’:
t.cpp:52:12: error: use of deleted function ‘FinalClassEx::FinalClassEx(FinalClassEx&&)’
return f;
^
t.cpp:43:7: note: ‘FinalClassEx::FinalClassEx(FinalClassEx&&)’ is implicitly deleted because the default definition would be ill-formed:
class FinalClassEx : public FinalClass
^~~~~~~~~~~~
t.cpp:43:7: error: use of deleted function ‘Base::Base(const Base&)’
t.cpp:7:5: note: declared here
Base(const Base&) = delete;
^~~~
root@ubuntu64:~# vi t.cpp +7
# comment line 7 //Base(const Base&) = delete;
root@ubuntu64:~#
root@ubuntu64:~# c++ t.cpp -std=c++17
root@ubuntu64:~#
all ok
Re: Виртуальное наследование и возврат объекта
От: rg45 СССР  
Дата: 11.11.19 22:29
Оценка: +1
Здравствуйте, _NN_, Вы писали:

_NN>Имеем иерархию классов. Base <|- Derived <|- FinalClass <|- FinalClassEx

_NN>Почему при виртуальном наследовании Derived от Base нельзя возвратить объект из функции, а без него можно ?

Вот поэтому: https://timsong-cpp.github.io/cppwp/class.base.init#7.
(Смотри самое последнее предложение):

. . .
A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Виртуальное наследование и возврат объекта
От: _NN_ www.nemerleweb.com
Дата: 11.11.19 22:30
Оценка:
Здравствуйте, reversecode, Вы писали:

R>all ok

Это то понятно.
Эта строка убивает перемещение сгенерированное компилятором.
    Base(const Base&) = delete;


Вопрос как влияет виртуальное наследование.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Виртуальное наследование и возврат объекта
От: reversecode google
Дата: 11.11.19 22:34
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, reversecode, Вы писали:


R>>all ok

_NN>Это то понятно.
_NN>Эта строка убивает перемещение сгенерированное компилятором.
_NN>
    Base(const Base&) = delete;


_NN>Вопрос как влияет виртуальное наследование.


влияет прямо
очень рекомендую не пользоваться тем чего не понимаете
в данном случае вы не понимаете как инициализируется виртуальное наследование
и без того конструктора оно не работает в вашем случае
Re[4]: Виртуальное наследование и возврат объекта
От: _NN_ www.nemerleweb.com
Дата: 11.11.19 22:43
Оценка:
Здравствуйте, reversecode, Вы писали:

R>Здравствуйте, _NN_, Вы писали:


_NN>>Здравствуйте, reversecode, Вы писали:


R>>>all ok

_NN>>Это то понятно.
_NN>>Эта строка убивает перемещение сгенерированное компилятором.
_NN>>
    Base(const Base&) = delete;


_NN>>Вопрос как влияет виртуальное наследование.


R>влияет прямо

R>очень рекомендую не пользоваться тем чего не понимаете
Я им и не пользуюсь, это стандартная библиотека пользуется

R>в данном случае вы не понимаете как инициализируется виртуальное наследование

R>и без того конструктора оно не работает в вашем случае

Ок, тогда другой вопрос.
Почему using FinalClass::FinalClass не работает, а явно объявить конструкторы работает ?

class FinalClassEx : public FinalClass
{
public:
    FinalClassEx() {}
    FinalClassEx(FinalClassEx&&) {}
}


Разве компилятор не должен брать конструкторы из класса FinalClass ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Виртуальное наследование и возврат объекта
От: rg45 СССР  
Дата: 11.11.19 22:53
Оценка: 16 (1) +1
Здравствуйте, _NN_, Вы писали:

_NN>Разве компилятор не должен брать конструкторы из класса FinalClass ?


Должен. Но фишка в том, что подобъект виртуального базового класса инициализируется только в most derived классе. Он не может быть проинициализирован в не most derived классе. Поэтому конструктор перемещения, объявленный в FinalClass не оказывает никакого влияния на удаленный конструктор перемещения класса Base. И тот отстается быть удаленным аж до самого FinalClassEx. А вместе с ним оказывается удаленным и конструктор перемещения класса FinalClassEx, если его не определить.

P.S. Вот смотри, все сказанное можно показать и на более простом примере конструктора по умолчанию:

http://coliru.stacked-crooked.com/a/57a7b3ffd941f41d
struct Base {
    explicit Base(int) {};
};

struct FinalClass : virtual Base {
    FinalClass() : Base(42) {}
};

struct FinalClassEx : FinalClass {
};

FinalClass fc; // Ok
FinalClassEx fcex; // error: use of deleted function 'FinalClassEx::FinalClassEx()'
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 12.11.2019 6:13 rg45 . Предыдущая версия . Еще …
Отредактировано 11.11.2019 23:47 rg45 . Предыдущая версия .
Отредактировано 11.11.2019 23:07 rg45 . Предыдущая версия .
Отредактировано 11.11.2019 22:59 rg45 . Предыдущая версия .
Отредактировано 11.11.2019 22:58 rg45 . Предыдущая версия .
Отредактировано 11.11.2019 22:55 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.