Crash prostego programu i prośba o review kodu

0

Cześć

Chciałem poćwiczyć inteligentne wskaźniki, w tym przypadku shared_ptr i akurat chciałem w to włączyć wzorzec budowniczy.
Program jest naprawdę trywialny i taki miał być. Wszystko puszczam w mainowym pliku, żeby było szybciej.

Jak uruchamiam, to pokazuje się komunikat, że program przestał działać i się wyłącza, więc pewnie jest jakieś naruszenie pamięci. Mógłby ktoś z Was rzcucić na to okiem i dać wskazówkę co jest źle?

Prosiłbym Was też o uwagi co jest do poprawienia, co robię źle itd.

Pozdrawiam

Pliki:
main.cpp

 #include <iostream>
#include "DomBudowniczy.hpp"
#include "Dom.hpp"
#include <memory>
using namespace std;

class IDomBudowniczy;

void stworzDom(shared_ptr<IDomBudowniczy> budowniczy);

int main()
{
    shared_ptr<DomBudowniczy> budowniczyDomu;
    stworzDom(budowniczyDomu);

    cout << "MONTE" << endl;

return 0;
}

void stworzDom(shared_ptr<IDomBudowniczy> budowniczy)
{
    budowniczy->stworzDom();
    budowniczy->ustawKolorDachu();
    budowniczy->ustawOkna();
    budowniczy->ustawSciany();

    auto dom = budowniczy->dajAdresDomu();
    cout << dom << endl;
}
 #ifndef DOM_HPP_
#define DOM_HPP_

#include <string>
#include <iostream>
using namespace std;

class Dom
{
public:
    Dom() : liczbaScian(0), kolorDachu(""), liczbaOkien(0)
    {}

    void ustawLiczbeScian(int l) { liczbaScian = l; }
    void ustawLiczbeOkien(int l) { liczbaOkien = l; }
    void ustawKolorDachu(std::string k) { kolorDachu = k; }

    friend ostream& operator<<(ostream& out, Dom dom)
    {
        out << "Dom: liczba scian: " << dom.liczbaScian << ", liczba okien: " << dom.liczbaOkien << ", kolor dachu: " << dom.kolorDachu << endl;
        return out;
    }

private:
    int liczbaScian;
    std::string kolorDachu;
    int liczbaOkien;
};



#endif /* DOM_HPP_ */
#ifndef DOMBUDOWNICZY_H_
#define DOMBUDOWNICZY_H_

#include "IDomBudowniczy.hpp"
#include "Dom.hpp"

class DomBudowniczy : public IDomBudowniczy
{
public:
    DomBudowniczy(){}
    virtual ~DomBudowniczy(){}

    virtual void stworzDom(){ dom = std::make_shared<Dom>(); }
    virtual void ustawSciany(int l = 4) { dom->ustawLiczbeScian(l); }
    virtual void ustawOkna(int l = 2) { dom->ustawLiczbeOkien(l); }
    virtual void ustawKolorDachu(std::string k = "Czerwony") { dom->ustawKolorDachu(k); }
    virtual std::shared_ptr<Dom> dajAdresDomu() { return dom; }

private:
    std::shared_ptr<Dom> dom;
};

#endif /* DOMBUDOWNICZY_H_ */
 
 #ifndef IDOMBUDOWNICZY_HPP_
#define IDOMBUDOWNICZY_HPP_

#include <string>
#include <memory>

class Dom;

class IDomBudowniczy
{
public:
    virtual void stworzDom(){}
    virtual void ustawSciany(int l = 0) = 0;
    virtual void ustawOkna(int l = 0) = 0;
    virtual void ustawKolorDachu(std::string k = "") = 0;
    virtual std::shared_ptr<Dom> dajAdresDomu() { return NULL; }

};



#endif /* IDOMBUDOWNICZY_HPP_ */
3

a gdzie jest new DomBudowniczy?

1

Nazwy sugerują, że próbujesz używać wzorca builder. Niestety nie do końca Ci się udało:

  1. Skoro jest builder, to dlaczego można skonstruować Dom publicznym konstruktorem? Powinien być dostępny tylko dla buildera.
  2. Dlaczego domyślny konstruktor Dom konstruuje dom bez ścian? Zaleca się, aby konstruktor tworzył od razu prawidłowy obiekt, gotowy do zamieszkania.
  3. Istota wzorca builder jest to, że klient najpierw ustawia własności obiektu, a na końcu woła build() czy jakiś tam inny odpowiednik (u Ciebie może być budujDom()) i dostaje obiekt. U Ciebie jest chyba na odwrót. Nie bardzo widzę sens uzywania Budowniczego tylko po to, aby za jego pośrednictwem zmieniać własności obiektu, który już otrzymałem, i który sam udostępnia mi metody do modyfikacji swojego stanu.

PS. Przewidujesz mieć jakieś inne implementacje interfejsu IDomBudowniczy? Interfejs z jedną implementacją to zwykle niepotrzebna biurokracja (oczywiście nie zawsze - ale każdy element w projekcie musi mieć uzasadnienie, a nie że "bo chciałem pokazać, że umiem dziedziczenie").

0

ad 1. Ok, racja. Powinienem konstruktor zrobić protected i zaprzyjażnić klasę budowniczego?
ad 2. Niedopatrzenie :) Skupiłem się na innych rzeczach.
ad 3. Czyli ten obiekt Budowniczego już w momencie tworzenia powinien mieć ustawione właściwości według których później wybuduje Dom, tak?

Tak, interfejs to furtka do dodania kolejnych podklas Budowniczego Domu.

0

Ad. 3: Niekoniecznie. To już zależy od tego czy chcesz wymusić na użytkowniku obowiązkowe podanie jakiś własności. Builder może mieć pewne wartości domyślne, ale może też nie mieć jakiejś wstępnie ustawionej i wtedy jeśli użytkownik buildera nie ustawi ich, to wywołanie build() powinno zakończyć się błędem.

0

Okey, dzięki za wytłumaczenie. A co z pierwszym pytaniem? :)

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