Dużo trudności sprawia czasem właściwe zdefiniowanie (przeciążenie) operatora przypisania dla klasy pochodnej.
Jeżeli w klasie bazowej jest zdefiniowany nieprywatny operator
przypisania, a w klasie pochodnej nie jest, to do przypisania
odziedziczonego podobiektu klasy bazowej zostanie użyty operator
przypisania zdefiniowany w klasie bazowej. Natomiast dla części
„własnej” obiektu klasy pochodnej zostanie wtedy użyte przypisanie
dostarczone przez system (a więc „pole po polu”; prawdopodobnie
nieprawidłowo, jeśli są w klasie pola wskaźnikowe).
Rozpatrzmy na przykład poniższy program, w którym definiujemy
prostą klasę
A
 i klasę dziedziczącą
B:
      1.  #include <iostream>
      2.  using namespace std;
      3.  
      4.  struct A {
      5.      char a;
      6.      A(char aa = 'a') {
      7.          a = aa;
      8.      }
      9.  
     10.      A& operator=(const A& aa) {
     11.          a = aa.a;
     12.          cout << "A::operator=()\n";
     13.          return *this;
     14.      }
     15.  };
     16.  
     17.  struct B: public A {
     18.      char b;
     19.      B(char bb = 'b') : A(bb) {
     20.          b = bb;
     21.      }
     22.  };
     23.  
     24.  int main() {
     25.      B b1(1),b2(2);
     26.      b1 = b2;
     27.  }
    A::operator=()
co świadczy o tym, że podczas wykonywania przypisania dla
obiektów klasy pochodnej 
B
 została automatycznie wywołana
metoda
operator=()
 z klasy nadrzędnej 
A.
Ta odziedziczona z klasy bazowej metoda
operator=()
nie może oczywiście wiedzieć o składowych klasy pochodnej,
których nie było w klasie bazowej.
Przeanalizujmy zatem sytuację, gdy operator przypisania został w klasie bazowej zdefiniowany, ale dla części „własnej” również chcemy przedefiniować przypisanie. Zatem w klasie pochodnej musimy również przeciążyć operator ' ='. Metoda przeciążająca operator przypisania w klasie pochodnej powinna uwzględniać składowe klasy pochodnej nieobecne w klasie bazowej oraz musi jawnie wywołać ten operator z klasy bazowej, by „zajął się” podobiektem z niej odziedziczonym: ponieważ zostanie wtedy uruchomiona wersja przypisania zdefiniowana w klasie pochodnej, więc dla części odziedziczonej metoda operator=() z klasy bazowej nie zostanie teraz wywołana „sama z siebie”.
Zauważmy, że można to zrobić przez jawne, „po nazwie”, wywołanie metody przeciążającej operator przypisania z klasy bazowej. Można też osiągnąć ten sam cel przez proste przypisanie do *this, jeśli tylko podpowiemy kompilatorowi, żeby traktował wskazywany obiekt jako obiekt klasy bazowej (obiektem tym jest podobiekt klasy bazowej zawarty w obiekcie klasy pochodnej). Wtedy bowiem, zgodnie z regułami przeciążania operatorów, na rzecz tego podobiektu wywołana zostanie funkcja operator=() zdefiniowana w klasie bazowej.
Brzmi to zawile, ale jest całkiem proste. Załóżmy, jak zwykle, że klasa B dziedziczy z klasy A. Załóżmy też, że w klasie A operator przypisania został przeciążony, czyli jest w niej zdefiniowana metoda operator=(). Parametrem tej metody jest referencja (zwykle z modyfikatorem const) do obiektu klasy A, ale, jak wiemy, można taką metodę wywołać z argumentem typu pochodnego, którym to argumentem będzie referencja do przypisywanego obiektu klasy pochodnej (czyli tego, który występuje po prawej stronie przypisania). Na marginesie zauważmy, że cały mechanizm nie zadziałałby, gdybyśmy w klasie A, najzupełniej legalnie, zdefiniowali metodę operator=() z parametrem typu A lub const A zamiast A& lub const A&. Tak więc, przedefiniowując operator przypisania w klasie pochodnej B, moglibyśmy napisać (zakładając, że definicja ta jest poza klasą):
       B& B::operator=(const B& b) {
           this->A::operator=(b);
           // ...
           return *this;
       }
W ten sposób, na rzecz
*this, a więc obiektu klasy
pochodnej 
B, który pojawił się po lewej stronie przypisania,
wywołujemy
jawnie metodę
operator=()
 z klasy bazowej kwalifikując
nazwę za pomocą operatora zakresu. Posyłamy jako argument przez
referencję obiekt
b, w więc ten, który pojawił się po
prawej stronie przypisania. Ten sam efekt można uzyskać też tak:
       B& B::operator=(const B& b) {
           (A&)(*this) = b;
           // ...
           return *this;
       }
W tej metodzie referencja do obiektu
*this
 klasy
B
została zrzutowana w górę do typu
A&: tak więc przypisanie
z trzeciej linii tego przykładu spowoduje automatycznie wywołanie
metody
operator=()
 z klasy bazowej
A, podobnie jak
w przypadku poprzednim. Oczywiście, zamiast rzutowania w stylu C,
czyli za pomocą
(A&)
możemy użyć operatora rzutowania
w stylu C++, czyli trzecią linię powyższego przykładu zastąpić
przez
static_cast<A&>(*this) = b;Wreszcie, równoważnie, można użyć rzutowania wskaźników i następnie wyłuskania (dereferencji) obiektu:
       B& B::operator=(const B& b) {
           *((A*)this) = b;
           // ...
           return *this;
       }
choć wygląda to chyba najmniej czytelnie.
W poniższym programie zademonstrowane są przeciążenia operatora
przypisania, konstruktory, w tym kopiujące, i destruktory dla
dwóch klas:
Osoba
 i dziedziczącej z niej klasy
Pracownik. W obu klasach istnieją pola wskaźnikowe, a więc
prawidłowe zdefiniowanie konstruktorów kopiujących, destruktorów
i operatorów przypisania jest niezbędne.
      1.  #include <iostream>
      2.  #include <cstring>
      3.  using namespace std;
      4.  
      5.  class Osoba {
      6.      char* nazwis;
      7.  public:
      8.      Osoba()
      9.          : nazwis(strcpy(new char[14], "Nazw.Nieznane"))
     10.      {
     11.          cout << "Konstr. domyslny Osoba: "
     12.               << nazwis << endl;
     13.      }
     14.  
     15.      Osoba(const char* n)
     16.          : nazwis(strcpy(new char[strlen(n)+1], n))
     17.      {
     18.          cout << "Konstr. char* Osoba: " << nazwis << endl;
     19.      }
     20.  
     21.      Osoba(const Osoba& os)
     22.          : nazwis(strcpy(new char[strlen(os.nazwis)+1],
     23.                                             os.nazwis))
     24.      {
     25.          cout << "Konstr. kopiujacy Osoba: "
     26.               << nazwis << endl;
     27.      }
     28.  
     29.      Osoba& operator=(const Osoba& os) {
     30.          if ( this != &os ) {
     31.              delete [] nazwis;
     32.              nazwis = strcpy(new char[strlen(os.nazwis)+1],
     33.                                                 os.nazwis);
     34.              cout << "Przypisanie Osoba: "
     35.                   << nazwis << endl;
     36.          }
     37.          return *this;
     38.      }
     39.  
     40.      ~Osoba() {
     41.          cout << "Usuwamy Osoba: " << nazwis << endl;
     42.          delete [] nazwis;
     43.      }
     44.  
     45.      const char* getNazwisko() const { return nazwis; }
     46.  };
     47.  
     48.  class Pracownik : public Osoba {
     49.      char* funkcja;
     50.  public:
     51.      Pracownik()
     52.          : funkcja(strcpy(new char[14], "Stan.Nieznane"))
     53.      {
     54.          cout << "Konstruktor domyslny Pracownik: "
     55.               << funkcja << endl;
     56.      }
     57.  
     58.      Pracownik(const char* s, const char* n)
     59.          : Osoba(n),funkcja(strcpy(new char[strlen(s)+1], s))
     60.      {
     61.          cout << "Konstruktor char* char* Pracownik: "
     62.               << funkcja << endl;
     63.      }
     64.  
     65.      Pracownik(const Pracownik& prac)
     66.          : Osoba(prac), funkcja(strcpy(new
     67.                char[strlen(prac.funkcja)+1],prac.funkcja))
     68.      {
     69.          cout << "Konstruktor kopiujacy Pracownik: "
     70.               << funkcja << endl;
     71.      }
     72.  
     73.      Pracownik& operator=(const Pracownik& prac) {
     74.          if ( this != &prac ) {
     75.              (Osoba&)(*this) = prac;
     76.              delete [] funkcja;
     77.              funkcja = strcpy(new
     78.                  char[strlen(prac.funkcja)+1],
     79.                  prac.funkcja);
     80.              cout << "Przypisanie Pracownik: "
     81.                   << funkcja << endl;
     82.          }
     83.          return *this;
     84.      }
     85.  
     86.      ~Pracownik() {
     87.          cout << "Usuwamy Pracownik: " << funkcja << endl;
     88.          delete [] funkcja;
     89.      }
     90.  
     91.      const char* getFunkcja() const { return funkcja; }
     92.  };
     93.  
     94.  int main() {
     95.      cout << "\nMain: Tworzymy obiekt nem" << endl;
     96.      Pracownik nem;
     97.      cout << "Main: obiekt nemo utworzony: "
     98.           << nem.getFunkcja() << " "
     99.           << nem.getNazwisko()   << endl;
    100.  
    101.      cout << "\nMain: Tworzymy obiekt mal" << endl;
    102.      Pracownik mal("Szef", "Malinowski");
    103.      cout << "Main: obiekt mal utworzony: "
    104.           << mal.getFunkcja() << " "
    105.           << mal.getNazwisko()   << endl;
    106.  
    107.      cout << "\nMain: Kopiujemy mal -> kop" << endl;
    108.      Pracownik kop(mal);
    109.      cout << "Main: obiekt kop utworzony: "
    110.           << kop.getFunkcja() << " "
    111.           << kop.getNazwisko()   << endl;
    112.  
    113.      cout << "\nMain: Przypisujemy nem = kop" << endl;
    114.      nem = kop;
    115.      cout << "Main: nem = kop przypisane: "
    116.           << nem.getFunkcja()  << " "
    117.           << nem.getNazwisko() << endl << endl;
    118.  }
    Main: Tworzymy obiekt nem
    Konstr. domyslny Osoba: Nazw.Nieznane
    Konstruktor domyslny Pracownik: Stan.Nieznane
    Main: obiekt nemo utworzony: Stan.Nieznane Nazw.Nieznane
    Main: Tworzymy obiekt mal
    Konstr. char* Osoba: Malinowski
    Konstruktor char* char* Pracownik: Szef
    Main: obiekt mal utworzony: Szef Malinowski
    Main: Kopiujemy mal -> kop
    Konstr. kopiujacy Osoba: Malinowski
    Konstruktor kopiujacy Pracownik: Szef
    Main: obiekt kop utworzony: Szef Malinowski
    Main: Przypisujemy nem = kop
    Przypisanie Osoba: Malinowski
    Przypisanie Pracownik: Szef
    Main: nem = kop przypisane: Szef Malinowski
    Usuwamy Pracownik: Szef
    Usuwamy Osoba: Malinowski
    Usuwamy Pracownik: Szef
    Usuwamy Osoba: Malinowski
    Usuwamy Pracownik: Szef
    Usuwamy Osoba: Malinowski
demonstruje kolejność wywoływania konstruktorów
i metod przeciążających operator przypisania. Po zakończeniu
programu wszystkie trzy obiekty są usuwane: co prawda wszystkie
przechowują takie same dane, ale są to trzy niezależne obiekty,
o czym świadczy fakt, że wszystkie wywołania destruktorów
powiodły się. Widzimy, że przy konstrukcji obiektów klasy
pochodnej
Pracownik
 najpierw tworzone są podobiekty klasy
Osoba. Natomiast podczas destrukcji najpierw wywoływany
jest destruktor klasy
Pracownik, a potem destruktor klasy
bazowej
Osoba.
T.R. Werner, 21 lutego 2016; 20:17