Według mojego ulubionego autora, Mr Scott Meyers, prywatny dziedzictwo i skład oznacza to samo sprawę, że aka ma związek. W ten sposób wszystko, co można uzyskać z kompozycji (ograniczanie, gdy klasa A ma klasy B jako jej członka) może być zdobyta przez prywatne dziedzictwo i Visa-Versa.

Więc następujący kod powinien być związkiem, ale z mojego punktu widzenia nie jest!

class A : private boost::noncopyable {.. this is irrelevant };

Czy ktoś może mi powiedzieć, że tęsknię? Lub jak ten kod może być wdrażany przez kompozycję?

12
Eduard Rostomyan 4 czerwiec 2018, 15:13

4 odpowiedzi

Najlepsza odpowiedź

Przykład można zaimplementować w ten sposób kompozycji:

class A {
private:
    class B {
        B(const B&) = delete;
        B& operator=(const B&) = delete;
    } b;
};

A jest niekopiowalny, ponieważ jego członek b jest niekopiowany.

15
vll 4 czerwiec 2018, 12:32

Twój przykład jest nadal związkiem.

Biorąc pod uwagę następną klasę jako przykład, który jest mniej więcej równoważny boost:noncopyable:

class X {
private:
    X(const X &);
    X &operator=(const X &);
public:
    X() {}
};

Następujące dwie klasy mają tę samą funkcjonalność:

class A : private X {
public:
    int a;
    char b;
};

class B {
public:
    int a;
    char b;
    X x;
};

W tym przykładzie A dziedziczy prywatnie z X podczas B zawiera instancję X. A nie można skopiować, ponieważ nie można wywołać konstruktora kopii rodzica, a B nie można skopiować, ponieważ nie może zadzwonić do konstruktora kopiowania jednego ze swoich członków.

A a1;
A a2(a1);   // error
B b1;
B b2(b1);   // error
6
dbush 4 czerwiec 2018, 12:29

boost::noncopyable nie ma prawdziwego znaczenia semantycznego, jest to tylko szczegóły realizacji, aby zezwolić dzieciom dzieci.

class A : private boost::noncopyable {};

A nie ma boost::noncopyable, ponieważ boost::noncopyable jest pusty, zarówno dosłownie, jak i znaczenia. Tutaj powiedziałbyś "A jest niekopiany", ale generalnie zgadzam się z punktem widzenia Meyers w ogólnym przypadku.

4
YSC 4 czerwiec 2018, 12:18

To pytanie można odpowiedzieć w sposób, który pozwala uniknąć specyfiki omawiania konkretnego przykładu. Klasa, która dziedziczy publicznie zaczyna się ze wszystkim, co definiuje semantykę jego rodzica - jego funkcje publiczne, a także jego zmienne państwowe, jeśli ma jakiekolwiek. Jeśli żadna z nich nie jest nadpisana, jest zgodna z Zasada zastępowania Lisku i jest szeroko - Zasada projektowania, że nadpisywanie tych właściwości powinny być wykonane w taki sposób, który zachowuje substytucyjność.

Dzięki prywatnym dziedziczeniu, żaden z tego nie ma zastosowania, chyba że programator zdecyduje się na wdrożenie (lub ponownego wdrożenia), w klasie pochodnej, wszystkie publiczne właściwości klasy rodzicielskiej, w sposób, który zachowuje substytucyjność. Ponieważ C ++ nie wymaga klasy prywatnej klasy do wdrażania wersji jego stosunkowych metod i zmiennych i zmiennych jego rodziców, nie jest to inne (inne niż niewielkie i formulacyjne zmiany w kodzie) niż w przypadku, gdy klasa pochodna, zamiast tego zawarta instancja klasy rodzicielskiej jako prywatny członek. W szczególności, z prywatnym dziedziczeniem, klasa pochodna nie jest w żadnym funkcjonalnym lub operacyjnym sposób podtytu rodzaju rodzica, a jeśli twój język traktuje zajęcia pochodne, jakby są podtypami, okazja dla nieporozumienia i zamieszania była Utworzono (choć należy zauważyć, że jeśli twój język ma sposób na egzekwowanie semantycznej ważności podtypów (które C ++ nie), wówczas skutecznie jest to kwestia stylu).

1
sdenham 6 czerwiec 2018, 14:56