C++ no default constructor exists for class

C++ no default constructor exists for class
« kdy: 21. 09. 2019, 15:59:52 »
Posledne 2 - 3 tyzdne som sa zacal zaujimat o C++, pretoze som pisal 1 projekt a jednu jeho cast by som asi najradsej napisal v C++.

Ten projekt isiel teraz bokom, lebo najprv sa ten jazyk musim poriadne naucit (aj keby to malo trvat roky), nakupil som si k nemu literaturu - 4 knihy. 2 hrube 2 tensie a postupne sa s tymto jazykom zoznamujem. Medzitym som zacal pisat jeden mensi projekt, taka utilitka aby som si v C++ nieco realne nakodil a vyskusal si moznosti jazyka a zistil kde vsade mam este medzery vo vedomostiach.

Ten jazyk ma dost chytil. Ale stale v nom mam pocit neistoty a obcas sa v duchu pytam WTF. Niektore konstrukcie v C++ sa mi zdaju ako z ineho sveta a v ziadnom inom jazyku som sa s takym niecim nestretol, ale na druhej strane ma bavi spoznavat nieco nove.

1. Teraz som napriklad narazil na jednu chybu a neviem co s nou  je na riadku 41 "no default constructor exists for class"

cast zdrojaka je tu: https://pastebin.com/M8vmiqiv

Vedeli by ste mi portadit ako to vyriesit?

2. Vedeli by ste mi pozret zdrojak ci niektore veci nerobim uplne zle? Pripustam ze tam mozem mat dost vazne logicke chyby, alebo mi tam mozu hrozit memory leaky holt som zaciatocnik. Napriklad na riadkoch 26, 27, 47, 48 sa robi kopia celeho vektoru hodnotou? nemal by som to skor riesit cez referenciu?

3. Tiez by ma zaujimalo ci existuje nejaky standard ktory by sa mal dodrziavat pri tvorbe nazvov identifikatorov. Lebo kazdy druhy zdrojak sa drzi niecoho ineho.


ByCzech

  • *****
  • 1 845
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #1 kdy: 21. 09. 2019, 16:17:24 »
Pro pochopení si přečtěte toto: https://stackoverflow.com/questions/4981241/no-default-constructor-exists-for-class a pak vytvořte správě default contructor pro třídu CustomSlot

Re:C++ no default constructor exists for class
« Odpověď #2 kdy: 21. 09. 2019, 16:18:39 »

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #3 kdy: 21. 09. 2019, 18:25:06 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Re:C++ no default constructor exists for class
« Odpověď #4 kdy: 21. 09. 2019, 19:32:13 »
Na tomhle serveru se pravidelně projevuje několik odborníků na jazyky a konkrétně C++. Já sám jsem hobbík a nedouk, dělám spíš do včel. A možná právě proto jsem na té správné úrovni, abych tady trochu něco okomentoval, ze své nevysoké pozorovatelny.

Takže po tomto disclaimeru ještě k bodům 2 a 3:


2.) jasně, návratovou hodnotou Vaší metody je vector, předávaný hodnotou. Inu proč ne :-) C++ to umí.

Osobně když tohle vidím, mám přirozený sklon říct "fuj, tohle se mělo předat odkazem". Ale ono ve skutečnosti záleží na situaci. V mnoha případech si řekněte "a zrovna ne, vždyť bych to o kus dál stejně musel kopírovat, a to nějak složitěji ručně/oklikou". A i kdyby to bylo trochu neefektivní... tak co? Záleží, jestli ta neefektivita něčemu vadí. Jestli si pomůžete v rovině "uživatelského dojmu", když místo předávky hodnotou předáte jenom referenci. Nebo napak v dané situaci (nějaký objektový model) je z hlediska fungování aplikace správně, předat odkaz, tzn. nikoli provádět hloubkovou kopii nějaké hierarchie instancí.

V obecnější rovině: C++ jakožto následník C má v genech takovou obecnou snahu, zamezit klasickým céčkovým nešvarům jako je opomenutí dealokace již nepotřebného objektu, nebo dereference pointeru na již dealokovaný objekt (nebo null pointeru) nebo opomenutí alokovaný objekt inicializovat na počáteční smysluplný stav apod. A snahou správců jazyka C++ vždy bylo, nabídnout základní primitiva a "programovací přístupy", která/které budou podobným situacím principielně předcházet. To že se do kontejnerů typu "vector" vkládají nejradši hodnoty (spíš než pointery nebo reference), to je přesně projev těchto snah. Nevím jestli má zásada "předávat hodnotou, nikoli odkazem" sama nějaké jméno, každopádně sousedí se zásadou RAII (1, 2). Totiž pokud používáte objekty, které se RAII drží, a předáváte si je hodnotou, tak máte v C++ prakticky po starostech s "vlastnictvím", životním cyklem instance, automatickou alokací a dealokací.

Odkud to C++ vlastně studujete? Máte nějakou představu o Céčku, umíte používat jeho pointery, nabil jste si o ně párkrát nos? Nebo znáte klasickou práci s "dynamickými daty" a ukazateli v nějakém jiném jazyce téhle generace? (Packal?) Už jste narazil na C++ reference a jejich rozdíl oproti klasickým pointerům? (C++ Reference jsou další taková finta, jak sice nepředávat hodnotou, ale zároveň se za každou cenu vyhnout situaci, kdy reference bude naplatná.) A potkáte strong pointery... a já osobně (neživím se tím) teď jak trochu dohledávám další čtení okolo, narazil jsem na dvě povídání, ze kterých mi jdou oči trochu křížem... Prostě jsem spíš nenapravitelný céčkař.

Osobně jsem i jako hobbík už tu a tam napsal nějaký kus softwaru, kde trochu rozsáhlejší datový model znemožňoval, používat prosté předávání hodnotou. Zkrátka to nedávalo smysl. Objekty na heapu byly pěkně navzájem prolinkované odkazy (často nakonec prostými pointery, nebo strong pointery) a předávání hodnotou by bylo koncepčně blbě, protože by tím vznikla pokaždé další nová instance objektu, nová kopie.

Čili osobně si z toho beru tolik, že ty syntaktické nástroje, jak si "samotížně" zajistit RAII a vyhnout se mrtvým pointerům, jsou dobré na úplně spodní vrstvu, úplně nejdrobnější součástky, ze kterých stavíte svou katedrálu. Na trochu vyšších vrstvách skladebnosti už si musíte sám nést odpovědnost za "vlastnictví" objektů a jejich životní cyklus. C++ Vám k tomu bude maximálně nápomocno - takže se můžete soustředit na těch několik momentů, kdy objekt přechází např. ze stavu "základní prázdný zhruba inicializovaný" do "plně zabydlený" do "připojený a aktivní" apod., můžete se soustředit na správný moment, kdy (a v jakém pořadí) má instance objektu automaticky dealokovat vlastněné objekty (při graceful shutdownu), držené přes nějaký kontejner pointerů apod. Došel jsem zhruba k intruzivním šablonám pro autodestrukci na bázi reference countingu... (v kombinaci se strong pointers). A jsem si vědom, že to je pořád velice "lopatí" úroveň programovací černé magie.


3.) konvence tvorby jmen... osobně vím cca o dvou rozšířených variantách:
 
A) to co je vidět v Linuxu = všechna písmenka malá a mezi slovy podtržítka
B) "maďarská notace", dost rozšířená v Microsoftím světě
C) občas je k vidění varianta "maximálně úsporná" = jména symbolů jsou 2-4 znaky dlouhé zkratky :-) Viz třeba zdrojáky Perlu.

Ona je to zřejmě podmnožina širšího "coding style". Obecně když přispíváte do nějakého projektu, měl byste se držet stávajícího stylu - vč. věcí jako kde dávat otvírací závorku bloku, kolik pevných mezer odpovídá tabulátoru apod.
Pokud začínáte na zelené louce svůj vlastní kousek softwaru, možná zvažte, ze kterého tábora bude převažující "odborné publikum".


Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #5 kdy: 21. 09. 2019, 20:08:28 »
A) to co je vidět v Linuxu = všechna písmenka malá a mezi slovy podtržítka
B) "maďarská notace", dost rozšířená v Microsoftím světě
C) občas je k vidění varianta "maximálně úsporná" = jména symbolů jsou 2-4 znaky dlouhé zkratky :-) Viz třeba zdrojáky Perlu.

Ad A) snake notace je OK.
Ad B) maďarské notace se zbavuje i Microsoft.
Ad C) tomu je třeba vyhnout se velkým obloukem.

Obecně by mělo platit, že "globálnější" proměnná by měla mít popisnější název než proměnná lokální. Řídicí proměnné cyklu mohou být klidně i jednoznakové i, j, k.

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #6 kdy: 21. 09. 2019, 21:02:17 »
Na tomhle serveru se pravidelně projevuje několik odborníků na jazyky a konkrétně C++. Já sám jsem hobbík a nedouk, dělám spíš do včel. A možná právě proto jsem na té správné úrovni, abych tady trochu něco okomentoval, ze své nevysoké pozorovatelny.

Takže po tomto disclaimeru ještě k bodům 2 a 3:


2.) jasně, návratovou hodnotou Vaší metody je vector, předávaný hodnotou. Inu proč ne :-) C++ to umí.

Osobně když tohle vidím, mám přirozený sklon říct "fuj, tohle se mělo předat odkazem". Ale ono ve skutečnosti záleží na situaci. V mnoha případech si řekněte "a zrovna ne, vždyť bych to o kus dál stejně musel kopírovat, a to nějak složitěji ručně/oklikou". A i kdyby to bylo trochu neefektivní... tak co? Záleží, jestli ta neefektivita něčemu vadí. Jestli si pomůžete v rovině "uživatelského dojmu", když místo předávky hodnotou předáte jenom referenci. Nebo napak v dané situaci (nějaký objektový model) je z hlediska fungování aplikace správně, předat odkaz, tzn. nikoli provádět hloubkovou kopii nějaké hierarchie instancí.

V obecnější rovině: C++ jakožto následník C má v genech takovou obecnou snahu, zamezit klasickým céčkovým nešvarům jako je opomenutí dealokace již nepotřebného objektu, nebo dereference pointeru na již dealokovaný objekt (nebo null pointeru) nebo opomenutí alokovaný objekt inicializovat na počáteční smysluplný stav apod. A snahou správců jazyka C++ vždy bylo, nabídnout základní primitiva a "programovací přístupy", která/které budou podobným situacím principielně předcházet. To že se do kontejnerů typu "vector" vkládají nejradši hodnoty (spíš než pointery nebo reference), to je přesně projev těchto snah. Nevím jestli má zásada "předávat hodnotou, nikoli odkazem" sama nějaké jméno, každopádně sousedí se zásadou RAII (1, 2). Totiž pokud používáte objekty, které se RAII drží, a předáváte si je hodnotou, tak máte v C++ prakticky po starostech s "vlastnictvím", životním cyklem instance, automatickou alokací a dealokací.

Odkud to C++ vlastně studujete? Máte nějakou představu o Céčku, umíte používat jeho pointery, nabil jste si o ně párkrát nos? Nebo znáte klasickou práci s "dynamickými daty" a ukazateli v nějakém jiném jazyce téhle generace? (Packal?) Už jste narazil na C++ reference a jejich rozdíl oproti klasickým pointerům? (C++ Reference jsou další taková finta, jak sice nepředávat hodnotou, ale zároveň se za každou cenu vyhnout situaci, kdy reference bude naplatná.) A potkáte strong pointery... a já osobně (neživím se tím) teď jak trochu dohledávám další čtení okolo, narazil jsem na dvě povídání, ze kterých mi jdou oči trochu křížem... Prostě jsem spíš nenapravitelný céčkař.

Osobně jsem i jako hobbík už tu a tam napsal nějaký kus softwaru, kde trochu rozsáhlejší datový model znemožňoval, používat prosté předávání hodnotou. Zkrátka to nedávalo smysl. Objekty na heapu byly pěkně navzájem prolinkované odkazy (často nakonec prostými pointery, nebo strong pointery) a předávání hodnotou by bylo koncepčně blbě, protože by tím vznikla pokaždé další nová instance objektu, nová kopie.

Čili osobně si z toho beru tolik, že ty syntaktické nástroje, jak si "samotížně" zajistit RAII a vyhnout se mrtvým pointerům, jsou dobré na úplně spodní vrstvu, úplně nejdrobnější součástky, ze kterých stavíte svou katedrálu. Na trochu vyšších vrstvách skladebnosti už si musíte sám nést odpovědnost za "vlastnictví" objektů a jejich životní cyklus. C++ Vám k tomu bude maximálně nápomocno - takže se můžete soustředit na těch několik momentů, kdy objekt přechází např. ze stavu "základní prázdný zhruba inicializovaný" do "plně zabydlený" do "připojený a aktivní" apod., můžete se soustředit na správný moment, kdy (a v jakém pořadí) má instance objektu automaticky dealokovat vlastněné objekty (při graceful shutdownu), držené přes nějaký kontejner pointerů apod. Došel jsem zhruba k intruzivním šablonám pro autodestrukci na bázi reference countingu... (v kombinaci se strong pointers). A jsem si vědom, že to je pořád velice "lopatí" úroveň programovací černé magie.


3.) konvence tvorby jmen... osobně vím cca o dvou rozšířených variantách:
 
A) to co je vidět v Linuxu = všechna písmenka malá a mezi slovy podtržítka
B) "maďarská notace", dost rozšířená v Microsoftím světě
C) občas je k vidění varianta "maximálně úsporná" = jména symbolů jsou 2-4 znaky dlouhé zkratky :-) Viz třeba zdrojáky Perlu.

Ona je to zřejmě podmnožina širšího "coding style". Obecně když přispíváte do nějakého projektu, měl byste se držet stávajícího stylu - vč. věcí jako kde dávat otvírací závorku bloku, kolik pevných mezer odpovídá tabulátoru apod.
Pokud začínáte na zelené louce svůj vlastní kousek softwaru, možná zvažte, ze kterého tábora bude převažující "odborné publikum".
V C++ je “předání hodnotou” jen sémantika, při návratu z funkce může objekt klidně zůstat na zásobníku nebo se provede move (tedy bez kopírování vnitřností).

Re:C++ no default constructor exists for class
« Odpověď #7 kdy: 21. 09. 2019, 23:31:28 »
Výborný zdroj na C++ je https://en.cppreference.com.

3.) konvence tvorby jmen... osobně vím cca o dvou rozšířených variantách:
 
A) to co je vidět v Linuxu = všechna písmenka malá a mezi slovy podtržítka
B) "maďarská notace", dost rozšířená v Microsoftím světě
C) občas je k vidění varianta "maximálně úsporná" = jména symbolů jsou 2-4 znaky dlouhé zkratky :-) Viz třeba zdrojáky Perlu.

Tak hlavně je buď snake_case notace
Kód: [Vybrat]
my_number, nebo camelCase
Kód: [Vybrat]
myNumber.
Nejdůležitější je pojmenovávat tak, aby bylo co nejjasnější, o co jde a také, aby ten styl byl jednotný.

( C) je samozřejmě blbost s Perlem nesouvisející, je rozdíl mezi built-in/idiomatickými proměnnými a tím, jak se pojmenovávají "uživatelské" proměnné.)
« Poslední změna: 21. 09. 2019, 23:34:07 od Cikáda »

Re:C++ no default constructor exists for class
« Odpověď #8 kdy: 22. 09. 2019, 12:49:53 »
Ahoj, zkus použít "constructor initialization list".  Přecházíš ze C# nebo Javy?

Kód: [Vybrat]
   
class CustomSlot
...
    public:
        CustomSlot(
            const unsigned int index,
            const KeyboardShortcut copy_shortcut,
            const KeyboardShortcut paste_shortcut
        )
            :_index(index),
            _copy_shortcut(copy_shortcut),
            _paste_shortcut(paste_shortcut)
        {}
...
};
« Poslední změna: 22. 09. 2019, 12:52:17 od uetoyo »

Re:C++ no default constructor exists for class
« Odpověď #9 kdy: 22. 09. 2019, 13:04:51 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Kromě toho, že to je ukázkový příklad, tak třída  (struktura) v C++ nemusí nic "umět". C++ není OO jazyk (ala C#/Java), klidně se dá pracovat se strukturama a volnýma funkcema ... nakonec popírá to OOP? Bonus: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=24&cad=rja&uact=8&ved=2ahUKEwjm0JGqo-TkAhXFCewKHT-2CW8QFjAXegQIBBAC&url=http%3A%2F%2Fwww.stroustrup.com%2Foopsla.pdf&usg=AOvVaw0GZ9o3j-mGGsNO9vXy9Etl;

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #10 kdy: 22. 09. 2019, 14:22:37 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Kromě toho, že to je ukázkový příklad, tak třída  (struktura) v C++ nemusí nic "umět". C++ není OO jazyk (ala C#/Java), klidně se dá pracovat se strukturama a volnýma funkcema ... nakonec popírá to OOP?

V tom případě může rovnou použít struct nebo třídu s veřejnými atributy (resp. read-only) a vyjde to nastejno - spíš lépe.

Re:C++ no default constructor exists for class
« Odpověď #11 kdy: 22. 09. 2019, 14:25:49 »

Dakujem ti za informáciami nabitý príspevok a sumár tvojich skúseností ale k tvojim otázkam: ja sa učím hlavne z kníh mám ich dosť veľa a keď niečomu nerozumiem tak si o tom prečítam celú kapitolu rad - radom vo všetkých štyroch, ale v tomto konkrétnom prípade (inicializacia objektu vnoreného membera) som sa k tomu ešte nedostal.

Tvoj post som si viac krát prečítal a aj si ho archivujem (ak dovolíš). Jo a s pointermi mám skúsenosti ešte s delphi a pascalu pamatám si že som ich tam občas používal hlavne pri práci s grafikou. A teraz som sa s nimi dostal do kontaktu aj v .NETe (v unsafe) C# má pointerovú aritmetiku skoro na takej úrovni ako C++ aj keď v C++ je to stále ešte o chlp lepšie a preto som sa rozhodol že jednu časť appky prepíšem z .NETu do natívnej podoby.

Ahoj, zkus použít "constructor initialization list".  Přecházíš ze C# nebo Javy?

Prechádzam z viacerých jazykov (C#, F#, JS, TS, PHP) všetky majú triedy na jedno kopyto, a nikde som sa nestretol s tým aby som takýmto spôsobom musel inicializovať aj vnoreného membera, vždy sa to takto robilo iba pri predkoch. A rád by som počul vysvetlenie prečo je to nutné aj pri vnorených objektoch.
« Poslední změna: 22. 09. 2019, 14:32:38 od fortran1986 »

Re:C++ no default constructor exists for class
« Odpověď #12 kdy: 22. 09. 2019, 14:27:40 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Kromě toho, že to je ukázkový příklad, tak třída  (struktura) v C++ nemusí nic "umět". C++ není OO jazyk (ala C#/Java), klidně se dá pracovat se strukturama a volnýma funkcema ... nakonec popírá to OOP?

V tom případě může rovnou použít struct nebo třídu s veřejnými atributy (resp. read-only) a vyjde to nastejno - spíš lépe.

Ale potom nebude immutable. Snažil som sa naemulovať immutable štruktúru ktorá sa dá len čítať. Okrem toho ja ako funkcionálny programátor nemám nič proti anemickým objektom.

Re:C++ no default constructor exists for class
« Odpověď #13 kdy: 22. 09. 2019, 14:43:57 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Kromě toho, že to je ukázkový příklad, tak třída  (struktura) v C++ nemusí nic "umět". C++ není OO jazyk (ala C#/Java), klidně se dá pracovat se strukturama a volnýma funkcema ... nakonec popírá to OOP?

V tom případě může rovnou použít struct nebo třídu s veřejnými atributy (resp. read-only) a vyjde to nastejno - spíš lépe.

Ale potom nebude immutable. Snažil som sa naemulovať immutable štruktúru ktorá sa dá len čítať. Okrem toho ja ako funkcionálny programátor nemám nič proti anemickým objektom.

Přidej si k privátním proměnným `const`.
A dál citace: "Basically when data members are declared constant they have to have some value before the object is constructed Hence we use member initializer so that before the object is constructed the data member has some value."

https://en.cppreference.com/w/cpp/language/initializer_list
https://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/

Pokud jsou to *immutable value objects*, tak ti chybí minimálně implementace `==`, `!=` a `std::hash`.
« Poslední změna: 22. 09. 2019, 14:47:50 od uetoyo »

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:C++ no default constructor exists for class
« Odpověď #14 kdy: 22. 09. 2019, 15:00:29 »
Ta třída má jednu zásadní vadu: Nic neumí. Vyvaruj se tvorby takových anemických tříd, dej do nich alespoň jednu metodu.

Kromě toho, že to je ukázkový příklad, tak třída  (struktura) v C++ nemusí nic "umět". C++ není OO jazyk (ala C#/Java), klidně se dá pracovat se strukturama a volnýma funkcema ... nakonec popírá to OOP?

V tom případě může rovnou použít struct nebo třídu s veřejnými atributy (resp. read-only) a vyjde to nastejno - spíš lépe.

Ale potom nebude immutable. Snažil som sa naemulovať immutable štruktúru ktorá sa dá len čítať. Okrem toho ja ako funkcionálny programátor nemám nič proti anemickým objektom.

Immutable je něco jiného než read-only?