Wątek przeniesiony 2019-01-02 12:01 z Newbie przez Adam Boduch.

Problem z przeciażeniem konstruktora w klasie.

0

Witam, Mam mały problem z przeciążeniem konstruktora w klasie. Co prawda poruszyłem go w innym temacie, ale podobno na tym forum dla każdego nowego pytania zakłada się oddzielny temat, co czynię.
A więc tak: stworzyłem prostą klasę i stworzyłem w niej dwa konstruktory. Jeden ma być domyślny bez żadnych parametrów, co ma umożliwić stworzenie klasy BEZ podawania żadnych wartości do jej pól. Drugi konstruktor jest wieloargumentowy i ma pozwolić na zainicjowanie pół przed stworzeniem klasy. Napisałem taki program:

#include <iostream>
#include <string>
#include <cctype>
#include <windows.h>

using namespace std;

class Osoba
{
private:
    string imie;
    int wiek;
    int wzrost;
public:
    Osoba() //konstruktor domyslny
    {
        imie="brak";
        wiek=0;
        wzrost=0;
    }
    Osoba(string imie="brak", int wiek=0, int wzrost=0) //konstruktor wieloargumentowy
    {
        this->imie=imie;
        this->wiek=wiek;
        this->wzrost=wzrost;
 
    }

    void wyswietl()
    {
        cout<<"Dane"<<endl;
        cout<<"Imie: "<<imie<<endl;
        cout<<"Wiek: "<<wiek<<endl;
        cout<<"Wzrost: "<<wzrost<<endl<<endl;
    }

};


int main()
{
    Osoba Karol1;
    //Karol.podaj();
    //Karol.pobierz("xyz",9,8);
    Karol1.wyswietl();

    Osoba Karol2("Jan",24,32);
    Karol2.wyswietl();

    Osoba Karol3("Jacek",42);
    Karol3.wyswietl();


    return 0;
}

I teraz pojawia się błąd kompilacji "error: call of overloaded 'Osoba()' is ambiguous". Dowiedziałem się już, że kompilator nie wie, które ma wybrać przeładowanie, ponieważ obydwa są sobie równe. Jednak jeżeli z konstruktora domyślnego usunę wszystkie linie i zostawię tylko coś takiego:

Osoba() //konstruktor domyslny
    {

    }
    Osoba(string imie="brak", int wiek=0, int wzrost=0) //konstruktor wieloargumentowy
    {
        this->imie=imie;
        this->wiek=wiek;
        this->wzrost=wzrost;
 
    }

To kompilator dalej informuje o problemie z wyborem przeładowania. Co ciekawe, jeżeli usunę z konstruktora wieloargumentowego wartość "brak"

Osoba(string imie, int wiek=0, int wzrost=0) //konstruktor wieloargumentowy - nie ma juz wartosci "brak" przy stringu

To program się bez problemu kompiluje. Wie ktoś o co chodzi? Dlaczego po usunięciu wartości domyślnej ze stringa program działa, a wcześniej nie?

2

Nie kompiluje się, ponieważ kompilator nie wie który konstruktor jest lepszy.

Na przykładzie trochę prostszym, może pomoże:

niech będzie funkcja print_n, która

void print_n(int n);

Wywołanie jest oczywiste, print_n(42) nie pozostawia złudzeń co się wykona

Rozważmy teraz dwa przypadki dodania domyślnego zachowania:

  1. dodajemy przeładowanie
void print_n(); // print zero
void print_n(int n); // print n

Wywołanie jest oczywiste, print_n() nie pozostawia złudzeń co się wykona

  1. dodajemy wartość domyślną
void print_n(int n=0); // print n

Wywołanie jest oczywiste, print_n() nie pozostawia złudzeń co się wykona


a teraz przypadek trzeci:

  1. zróbmy oba naraz
void print_n(); // print zero
void print_n(int n=0); // print n

Napisałem print_n(), które jest lepsze i dlaczego?

Ogółem, mam wrażenie że masz problem XY. W językach, które nie oferują parametrów domyślnych, przeładowania funkcji są używane jako ich imitacja, ale w C++ nie masz takiej potrzeby. Jak chcesz zaznaczyć, że masz niezainicjalizowany obiekt to użyj std::optional

0

Dobra, już rozumiem, a możesz powiedzieć dlaczego akurat po usunięciu domyślnej wartości string, program już się skompilował?
I o co chodzi z tym, że mam problem z XY? xd

2

Dobra, już rozumiem, a możesz powiedzieć dlaczego akurat po usunięciu domyślnej wartości string, program już się skompilował?

Czyli nie rozumiesz ;​)

Program się skompilował, bo nie było niejasności który konstruktor domyślny wybrać - bo został tylko jeden, a wcześniej utworzyłeś dwa.

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