Dziedziczenie konstruktora przenoszącego

0

Cześć,

mam problem z dziedziczeniem konstruktora przenoszącego:

#include <iostream>

class BaseClass
{
public:
    BaseClass() {}

    BaseClass( const BaseClass &other ) = delete;
    BaseClass( BaseClass &&other ) {}

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

    ~BaseClass() {}

    static BaseClass Create()
    {
        return BaseClass();
    }
};

class Foo : public BaseClass
{
public:
    using BaseClass::BaseClass;
    using BaseClass::operator=;

    //Foo( BaseClass &&other ) : BaseClass( std::move( other ) ) {}
};

int main()
{
    Foo f = Foo::Create();
}
<source>:31:9: error: no viable conversion from 'BaseClass' to 'Foo'
   31 |     Foo f = Foo::Create();
      |         ^   ~~~~~~~~~~~~~
<source>:22:7: note: candidate constructor (the implicit copy constructor) not viable: cannot bind base class object of type 'BaseClass' to derived class reference 'const Foo &' for 1st argument
   22 | class Foo : public BaseClass
      |       ^~~
<source>:22:7: note: candidate constructor (the implicit move constructor) not viable: cannot bind base class object of type 'BaseClass' to derived class reference 'Foo &&' for 1st argument
   22 | class Foo : public BaseClass

Błąd kompilacji występuje na wszystkich głównych kompilatorach: msvc, gcc, clang.

Problem znika gdy dodam taki konstruktor do klasy Foo:

    Foo( BaseClass &&other ) : BaseClass( std::move( other ) ) {}

Ale nie rozumiem. Przecież using BaseClass::BaseClass powinno dziedziczyć wszystkie konstruktory?

https://godbolt.org/z/bsK67EbdW

Co ciekawe, operator= działa poprawnie i się kompiluje.

    Foo f;
    f = Foo::Create();

https://godbolt.org/z/sG886Yef9

Czy ktoś jest w stanie mi to sensownie wytłumaczyć?

1

konstruktora przenoszącego się nie dziedziczy ale jak chcesz go użyć to:

#include <iostream>
#include <utility>

class Base {
public:
    Base() { std::cout << "Base default constructor\n"; }
    Base(Base&&) { std::cout << "Base move constructor\n"; }
};

class Derived : public Base {
public:
    Derived() { std::cout << "Derived default constructor\n"; }
    Derived(Derived&& other) : Base(std::move(other)) { std::cout << "Derived move constructor\n"; }
};

int main() {
    Derived d1;
    Derived d2(std::move(d1));
    return 0;
}
6
zkubinski napisał(a):

konstruktora przenoszącego się nie dziedziczy ale jak chcesz go użyć to:

Żadnego konstruktora się nie dziedziczy

0

zastanów się nad

Foo f = Foo::Create();

i tym ponizej

#include <iostream>

class BaseClass
{
public:
    BaseClass() {}

    BaseClass( const BaseClass &other ) = delete;
    BaseClass( BaseClass &&other ) {}

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

    ~BaseClass() {}

    static BaseClass Create()
    {
        return BaseClass();
    }
};

class Foo : public BaseClass
{
public:
    using BaseClass::BaseClass;
    using BaseClass::operator=;

    //Foo( BaseClass &&other ) : BaseClass( std::move( other ) ) {}
};

int main()
{
    BaseClass* f = new Foo();
    BaseClass g = BaseClass::Create();
}

edit:
dobra żeby nie było bo nie ma co robić zagadek chodzi o konwersję, bo to ci ten konstruktor przenoszący

//Foo( BaseClass &&other ) : BaseClass( std::move( other ) ) {}

2

Copy i move konstruktory nie są dziedziczone (mówiąc ściślej są wyłączone z listy overloadu podczas rozpatrywania, które odziedziczone konstruktory są możliwe do wygenerowania przez klasę pochodną).

Sekcja draftu standardu C++20, która opisuje to zachowanie to 12.4.2.1 (8):

A constructor inherited from class type C (11.10.4) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.

1 użytkowników online, w tym zalogowanych: 0, gości: 1