#include <stdio.h>
#include <string.h>

class Lancuch {

private:                
    char *nazwa_klasy;	// niedostepne w ZmiennyLancuch

protected:              
    char *znaki;
    int dlugosc;

public:                 

    Lancuch():          
        znaki(NULL),
        dlugosc(0)      // lista inicjująca
    {
        printf("Konstruktor Lancuch bezparametrowy\n");
    }

    Lancuch(const char *str); // inny konstruktor - deklaracja

    ~Lancuch();               // destruktor

    int podaj_dlugosc();            //
    char* podaj_lancuch();          // deklaracje metod
    char podaj_znak(int ktory);     //

}; // średnik jest niezbędny !!!

class ZmiennyLancuch: public Lancuch
{
    public:
        ZmiennyLancuch() {
            printf("Konstruktor ZmiennyLancuch bezparametrowy\n");
        }
        ZmiennyLancuch(const char *str):    // przykrywamy konstruktor 
                                            // z Lancuch
            Lancuch(str)                    // konstruktor bazowy
        {
            printf("Konstruktor ZmiennyLancuch z const char*\n");
        }
        ~ZmiennyLancuch() {
            printf("Destruktor ZmiennyLancuch\n");
        }

        // nowa metoda, rozszerzająca
        // funkcjonalność Lancuch
        void ustal_lancuch(const char *str);    

};

// implementacje metod
Lancuch::Lancuch(const char *str) {
    znaki = strdup(str);
    dlugosc = (int) strlen(str);
    printf("Konstruktor Lancuch z const char*\n");
}

Lancuch::~Lancuch() {
    if (znaki) delete znaki;
    printf("Destruktor Lancuch\n");
}

int Lancuch::podaj_dlugosc() {
    return dlugosc;
}

char* Lancuch::podaj_lancuch() {
    if (znaki) return znaki;
    else return "\0";
}

char Lancuch::podaj_znak(int ktory) {
    if (ktory>=dlugosc) return '\0';
    else return znaki[ktory];
}

void ZmiennyLancuch::ustal_lancuch(const char *str) {
    if (znaki) delete znaki;
    znaki = strdup(str);
    dlugosc = (int) strlen(str);
}

int main() {
    ZmiennyLancuch *l1 = new ZmiennyLancuch();
    ZmiennyLancuch *l2 = new ZmiennyLancuch("TOMEK");
	Lancuch *l3 = new ZmiennyLancuch("ZMIENNY CZY NIE?");

    l1->ustal_lancuch("ABCDE");

	// nie da sie bezposrednio l3->ustal_lancuch() bo
	// formalnie l3 jest klasy Lancuch, ale mozna tak:
	((ZmiennyLancuch*) l3)->ustal_lancuch("EFG");

    printf("%s, %s, %s\n",l1->podaj_lancuch(), 
	                      l2->podaj_lancuch(),
	                      l3->podaj_lancuch()
						  );
    // można wywołać podaj_lancuch() z obiektu klasy ZmiennyLancuch
    // ponieważ ZmiennyLancuch dziedziczy wszystkie nieprywatne metody
    // i pola z Lancuch, w tym także podaj_lancuch()

    delete l1;
    delete l2;
	delete l3;

    return 0;
    
}


