const unique_ptr reference

0

Witam,
Dla przykładu stworzyłem taką klasę:

class Dog
{
private:
    unsigned age;
    std::string name;
    std::unique_ptr<Owner> owner;
public:
    Dog() {std:: cout << "Dog Default constructor" << std::endl;}
    Dog(const unsigned int& _age, const std::string& _name, const std::unique_ptr<Owner>& _o) : age(_age), name(_name), owner(std::move(_o)) {std:: cout << "Dog parameter constructor" << std::endl;}
    Dog(const Dog& lReference) : age(lReference.age), name(lReference.name) { std::cout << " Dog Copy Constructor" <<std::endl; }
    Dog& operator=(const Dog& lReference)
    {
        std::cout << "Dog operator= called." << std::endl;
        if(this != &lReference)
        {
            age = lReference.age;
            name = lReference.name;
        }
        return *this;
    }
    ~Dog() {std::cout << "Dog Destructor" <<std::endl; }
    const std::string& getName() const
    {
        return name;
    }
    void setName(const std::string& _name)
    {
        this->name = _name;
    }
};

Skompilowanie powyższego kodu skutkuje błędem:

błąd: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Owner; _Dp = std::default_delete<Owner>]' Dog(const unsigned int& _age, const std::string& _name, const std::unique_ptr<Owner>& _o) : age(_age), name(_name), owner(std::move(_o)) {std:: cout << "Dog parameter constructor" << std::endl;}

Próbuję wywołać konstruktor kopiujący na unique_ptr co jest zabronione.
Nie rozumiem dlaczego przekazanie unique_ptr przez const reference powoduje wywoluje probe jego skopiowania, natomiast przekazanie przez sama reference (bez const) juz nie.. Będę wdzięczny za wytłumaczenie w miarę przystępny sposób.

0

std::move(_o) rzutuje na rvalue referencję, ale jeśli _o jest const, to efektywnym typem będzie unique_ptr<Owner> const&& z którego przenieść nie możesz. Wobec czego overload resolution znajduje kolejny akceptowalny konstruktor - kopiujący - i próbuje go użyć.

2

Powinno być tak:

Dog(int _age, const std::string& _name, std::unique_ptr<Owner>&& _o) 

Symbole nie powinny się zaczynać od _.

Poza tym coś jest źle. Owner oznacza właściciela, czyli oczekiwana relacja jest taka, że to właściciel odpowiada za psa. Jeden właściciel może mieć wiele psów, ale pies ma jednego właściciela.

Zapewne to Owner powinien mieć unique_ptr<Dog>, a Dog powinien mięc jedynie surowy wskaźnik do Owner.

0

A jaki jest aktualny sposób na nazewnictwo symboli ?

1

Można spokojnie użyć tego samego symbolu w nazwie arg co w nazwie pola klasy. Kompilator powinien bez problemu je rozróżnić. Jeśli jednak powstanie jakiś konflikt nazw lub niejednoznaczność użyj słowa this dla składowej klasy.
Np. pole age i argument age mogą mieć tą samą nazwę. Nie trzeba dodatkowych ozdobników przy nazwach.

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