Inicjowanie stringa wewnątrz klasy.

0

Witam.
Tworzę rodzinę klas Wyjątków. Każdy wyjątek to oddzielna podklasa (taki wymóg).
Każda klasa posiada stringa z linią, w której wystąpił błąd i stringa z informacją dla użytkownika co jest nie tak.
Chciałbym móc zainicjalizować stringa z informacją już w ciele klasy, niestety kompilator krzyczy, że robię to niezgodnie z ISO C++
co powinienem zmienić?

#ifndef WYJATKI_H
#define WYJATKI_H
#include <string>
using namespace std;
class Exc
{
    protected:
    string blednaLinia;
   // string opisBledu;
    Exc(){cout<<"Error! ";}
};

class Exc1 : public Exc
{
    string opisBledu = "Nie podano pierwszego argumentu dyrektywy #define!\n";
    Exc1(string blednaLinia) : blednaLinia(blednaLinia)
    {
        cout<<opisBledu<<"W linii: "<<blednaLinia;
    }
}

class Exc2 : public Exc
{
    opisBledu = "Nie podano drugiego argumentu dyrektywy #define!\n";
    Exc2(string blednaLinia) : blednaLinia(blednaLinia)
    {
        cout<<opisBledu<<"W linii: "<<blednaLinia;
    }
}

class Exc3 : public Exc
{
    opisBledu = "Podano nadmiarowy argument dyrektywy #undef!\n";
    Exc1(string blednaLinia) : blednaLinia(blednaLinia)
    {
        cout<<opisBledu<<"W linii: "<<blednaLinia;
    }
}


#endif

16|error: making 'opisBledu' static|
16|error: invalid in-class initialization of static data member of non-integral type 'std::string'|

Dlaczego Exc1 niby nie posiada pola "blednaLinia" skoro dziedziczy je po Exc ?

In constructor 'Exc1::Exc1(std::string)':|
17|error: class 'Exc1' does not have any field named 'blednaLinia'|

1

Co do "inicjacji" stringa, to do tego służy konstruktor klasy. Jest to funkcja która uruchamia się "automatycznie" przy każdym tworzeniu obiektu danej klasy, więc od strony pozostałej części programu niczym nie będzie różnić się od inicjacji. A możliwości ma takie jak zwykłą funkcja poza nadawaniem wartości "początkowych" zmiennym , może np przyjmować dane oraz wyświetlać je.

0

zrozumialem, ze opisBledu = "Podano nadmiarowy argument dyrektywy #undef!\n"; mam wrzucić do konstruktora
wrzucilem, działa. pozostaje pytanie dlaczego nie widzi pola, które dziedziczy(string blednaLinia)?

Dobra, olałem to i zrobiłem w ten sposób:

class Exc2 : public Exc
{
    Exc2(string blednaLinia)
    {
        blednaLinia = blednaLinia;
        opisBledu = "Nie podano drugiego argumentu dyrektywy #define!\n";
        cout<<opisBledu<<"W linii: "<<blednaLinia;
    }
};

mimo wszystko nadal ciekawi mnie dlaczego nie mogę tak zrobić

0

Ależ go widzi tylko że przykrywasz go parametrem.
this->blednaLinia = blednaLinia;

0

@Sztucznooki zalecane jest jednak inicjowanie zmiennych klasy przez listę inicjalizującą w konstruktorze. Wygląda to tak:

class Exc
{
    public:
    Exc( string _blednaLinia ) : blednaLinia( _blednaLinia ) {}  // zastosowanie listy inicjalizującej
    protected:
    string blednaLinia;
   // string opisBledu;
    Exc(){cout<<"Error! ";}
    virtual ~Exc(){}
};
 
class Exc2 : public Exc
{
    Exc2(string _blednaLinia) : Exc( _blednaLinia ) // zastosowanie listy inicjalizującej
    {
        opisBledu = "Nie podano drugiego argumentu dyrektywy #define!\n";
        cout<<opisBledu<<"W linii: "<<blednaLinia;
    }
};

A tak poza tym jeśli już mówimy o dziedziczeniu a o czym nie wspomniał wszechwiedzący, czepliwy @_13th_Dragon klasa bazowa powinna mieć wirtualny destruktor.

Edyta uzupełniła kod o klasę bazową oraz zwróciła uwagę na destruktor.

0

@_13th_Dragon nie widzę sensu robienia drugiej klasy na opis jak klasa ExcOp bo dodaje tylko opis. Inna sprawa - zrób teraz w kodzie:

Exc3 test( "lol" ); 
// jaki wynik? error: 'Exc3::Exc3(std::string)' is private

Konstruktor w pochodnych musi być publiczny. Jeśli chcemy natomiast aby bazowa nie była klasą, którą można tworzyć to musimy zrobić czysto wirtualny destruktor, lub np. zadeklarować konstruktor domyślny w sekcji private aby nie był dostępny.

Edyta sprecyzowała że chodzi nie tyle o wirtualny destruktor a czysto wirtualny

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