Премини към съдържанието
15 години Kaldata.com – време е да почерпим! Прочети още... ×

Препоръчан отговор


Здравейте, имам въпрос  и той е къде греша:

#include <iostream>using namespace std; class cena{public:int beton,stuklo; cena(int x, int y=1){beton = x ;stuklo = y;} cena(){} void write() const{cout << beton << endl << stuklo << endl;} }; int main(){cena kushta1(3,1);cena kushta2();kushta2 = kushta1;cout << kushta2.beton << endl << kushta2.stuklo;  cin.sync();cin.get();return 0 ;}

Изкарва ми грешка на реда, в който имаме kushta2 = kushta1;

Нещо не ми е ясна много работата, когато променяме тези конструктори как стават работите.Мислех че съм го разбрал, но явно не съм.Ще се радвам, ако някой ми обясни къде ми е грешката и да обясни защо.Благодаря предварително.

Редактирано от rusrusrus (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Здравейте, 

 

Поне на пръв поглед ми се струва, че нямате дефиниран copy-constructor, нито пък оператор '=' Ви е предефиниран за типа 'cena'

 

Пробвайте да дефинирате съответния копи конструктор и да предефинирате оператор = и вижте дали ще имате отново проблеми.

 

Copy Constructor

Operator Overloading

 

Поздрави !

Редактирано от soundtracker (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Здравейте, имам въпрос  и той е къде греша:

Изкарва ми грешка на реда, в който имаме kushta2 = kushta1;

Нещо не ми е ясна много работата, когато променяме тези конструктори как стават работите.

Не мога да разбера, защо толкова подценявате компилатора и съобщенията му за грешки. Ако вие не ги разбирате, поне ги пишете тук, когато търсите помощ. В този случай, дори на мен ми беше трудно да преценя, защо точно там ти дава грешка (очаквах да е на предния ред).

Обяснението е следното. Тук:

cena kushta2();

Имаме двусмислен израз. Ти си мислиш, че създаваш обект от клас cena. И така щеше да стане ако имаше конструктор по подразбиране - какъвто нямаш.

Редакция: Всъщност за да извикаш конструкторът по подразбиране трябва да махнеш скобите. Не забелязах, че все пак имаш конструктор по подразбиране.

Обаче това може да се възприеме и като деклариране на функция kyshta2, която връща обект от клас cena. Така го приема и компилаторът. След това ти пише грешка, че се опитваш да присвоиш стойност на функция.

Декларирай си конструктор по подразбиране (т.е. без параметри) и това ще ти оправи проблема. Относно копиращ конструктор и предефиниран оператор за присвояване, виж по-долу:

Поне на пръв поглед ми се струва, че нямате дефиниран copy-constructor, нито пък оператор '=' Ви е предефиниран за типа 'cena'

Всъщност, класовете винаги имат копиращ конструктор и оператор за присвояване, дори и да не им е дефиниран изрично такъв. Специални са необходими само за класове с динамично заделяни ресурси или които изискват специални условия за копиране. В случая няма нужда. Правилото за голямата тройка.

Редактирано от flare (преглед на промените)
  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Всъщност, класовете винаги имат копиращ конструктор и оператор за присвояване, дори и да не им е дефиниран изрично такъв. Специални са необходими само за класове с динамично заделяни ресурси или които изискват специални условия за копиране. В случая няма нужда. Правилото за голямата тройка.

Вярно, че в този случай нямаше нужда, но може би като добра практика за обучаващия се, е да си ги разписва, за да му стане като навик - поне аз рядко имах щастието да пиша класове, в които не се ползва динамична памет и затова точно липсата им ми се наби на очи първо. 

 

Поздрави и Весели празници :) !

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Вярно, че в този случай нямаше нужда, но може би като добра практика за обучаващия се, е да си ги разписва, за да му стане като навик - поне аз рядко имах щастието да пиша класове, в които не се ползва динамична памет и затова точно липсата им ми се наби на очи първо. Поздрави и Весели празници :) !

За тренировка става.Ами, аз съм привърженик на on-need-basis нещата. Примерно, ако видя дефиниран копиращ конструктор на такъв клас, в реален код, ще се чудя поне 15 минути, защо аджеба е направен и къде е уловката. Излишният код затруднява четенето, поддръжката и увеличава вероятността за грешки.Весели празници и на теб!

  • Харесва ми 2

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Когато изтрих () след cena.kushta1 всичко се оправи. Съвсем изключих, че го приема като функция.Иначе аз default constructor си имам. Този, който е cena()

{}

Не бях сигурен дали той трябва да се прави винаги default constructor. По- скоро си мислех, че него винаги си го има, просто аз мога да направя така, че той да бъде различен - например, в моят случай, beton = 1 , stuklo = 2; 

Т.е. когато създам cena.kushta1  и автоматично kushta1.beton = 1  и  kushta1.stuklo = 2; Мислех, че ако не съм създавал конструктор без параметри, то този стандартния си остава така, а явно каквито и конструктори да създавам, то е задължително после да напиша поне:

cena() 

{}

Нали така?

Имам и още един тъп въпрос. Понякога, когато си пиша нещо в компилатора (явно аз правя нещо) и вместо курсора ми да е между 2 букви, то той винаги е върху буква и я замества, когато напиша нещо. Например, ако почна от началото на един ред и задържа space, то целият ред ще се изтрие ( вместо да измести символите нататък).  Надявам се ,че се разбира за какво говоря. Не знам как да го оправя без да затворя компилатора. Може това да е малко тъп въпрос, но как мога да оправя това ? 

Благодаря много  и на двама ви. Весели празници и всичко наааай-най.

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Когато изтрих () след cena.kushta1 всичко се оправи. Съвсем изключих, че го приема като функция.Иначе аз default constructor си имам. Този, който е cena(){}Не бях сигурен дали той трябва да се прави винаги default constructor. По- скоро си мислех, че него винаги си го има, просто аз мога да направя така, че той да бъде различен - например, в моят случай, beton = 1 , stuklo = 2; Т.е. когато създам cena.kushta1  и автоматично kushta1.beton = 1  и  kushta1.stuklo = 2; Мислех, че ако не съм създавал конструктор без параметри, то този стандартния си остава така, а явно каквито и конструктори да създавам, то е задължително после да напиша поне:cena() {}Нали така?

Конструктор по подразбиране се създава автоматично, само ако не си дефинирал никакъв друг конструктор. Ако си дефинирал дори и един твой конструктор, независимо от броя и вида параметри, се ползват само изрично дефинираните.

Имам и още един тъп въпрос. Понякога, когато си пиша нещо в компилатора (явно аз правя нещо) и вместо курсора ми да е между 2 букви, то той винаги е върху буква и я замества, когато напиша нещо. Например, ако почна от началото на един ред и задържа space, то целият ред ще се изтрие ( вместо да измести символите нататък).  Надявам се ,че се разбира за какво говоря. Не знам как да го оправя без да затворя компилатора. Може това да е малко тъп въпрос, но как мога да оправя това ? Благодаря много  и на двама ви. Весели празници и всичко наааай-най.

Първо, моля да си изясниш понятията: редактор, компилатор и IDE(integrated development enviromnent). Най-вероятно ползваш последното, което е някаква комбинация от първите две + още полезни инструменти като дебъгер. Проблемът ти е с редактора, не с компилатора. Случайно да натискаш клавиша Insert? Той има навика да прави такива неща. Натисни го пак и ще се оправи.

Благодаря за пожеланията и Весели празници :)

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Не мисля, че натискам insert (или поне явно, може да правя някаква клавищна комбинация).Иначе използвам Visual Studio 2012.

Искам също да попитам защо при следната програма на екрана се извеждат 214161 ? Как възприема компилаторът нещата.Ето я и програмата 

 #include <iostream>using namespace std; class masiven{public:int x,y;masiven(int a = 0,int b=1){x = a;y = b;}};  int main(){masiven nov[3] = { (1,2) , (3,4) , (5,6)};cout << nov[0].x <<nov[0].y << nov[1].x << nov[1].y << nov[2].x << nov[2].y;cin.sync();cin.get();return 0;}П.П. май просто компилаторът първо прати nov[0].x = 1, а после го прави 2.
Редактирано от rusrusrus (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Имам  и още един въпрос .Може да е малко глупав. Той вече не е по темата с класове.Ето го и него: когато имаме

cout << setprecision(4) << scientific << 0.145555 ;

Аз мислех, че трябва да изведе на екрана 1.4556e-001 , а то се изведе 1.4555e-001 . При scientific не се ли използва винаги закръгляне?

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

П.П. май просто компилаторът първо прати nov[0].x = 1, а после го прави 2.

Компилторът не си пада по свободни съчинения. Неявна инициализация с двойки (изобщо повече от един) параметри в C++ няма. За да направиш такава, трябва да извикаш конструктора изрично:
masiven nov[3] = { masiven(1,2) , masiven(3,4) , masiven(5,6)};
Вместо това, компилаторът се опитва да "преведе" това, което му казваш по начин, който разбира. И тук идваме до непознатия на мнозина оператор ",". Той изпълнява всеки един от изразите и връща стойността на последния. Тоест написаното се свежда до:
masiven nov[3] = { 2 , 4 , 6};
Едва след това се опитва да инициализира "нещо" с тия стойности и вижда че това нещо е масив от клас masiven. Проверява има ли конструктор, който приема параметър едно цяло число - има (защото вторият параметър е пожелателен) и го извиква. Това е.

Имам  и още един въпрос .Може да е малко глупав. Той вече не е по темата с класове.Ето го и него: когато имамеcout << setprecision(4) << scientific << 0.145555 ;Аз мислех, че трябва да изведе на екрана 1.4556e-001 , а то се изведе 1.4555e-001 . При scientific не се ли използва винаги закръгляне?

Ползва. Обаче дробните числа в програмирането не са това, което изглеждат. Например някои числа, които са крайни дроби в десетична бройна система, не са такива в двоична или са малко по-дългички. Едно такова число може да "изглежда", че завършва на 5, но да кажем да в действителното представяне е (импровизирам) 1.45554998... И тогава, като го закръглиш... Сещаш се.
  • Харесва ми 2

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

...

Привет ! Само като едно малко допълнение към колегата да добавя. Това, което е "спасявало" работата да се "скалъпи" и тоя масив да се инициализира "някак си" са параметрите по подразбиране, които са зададени в конструктора на класа.Ако се махнат, нещата придобиват друг вид:

masiven(int a,int b)

=>

main.cpp: In function 'int main()':main.cpp:18:41: error: conversion from 'int' to non-scalar type 'masiven' requestedmasiven nov[3] = { (1,2) , (3,4) , (5,6)};                                                                ^main.cpp:18:41: error: conversion from 'int' to non-scalar type 'masiven' requestedmain.cpp:18:41: error: conversion from 'int' to non-scalar type 'masiven' requested

 Лично аз избягвам да ползвам конструктори с параметри по подразбиране - празен или непълен конструктор, който да си присвоява default-ни стойности за променливи на обекта в тялото ми се струва по - четим и разбираем.

 

Поздрави и Весели празници !

 

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

За това за масива ми беше ясно как трябва да стане просто не знаех как го възприема компилатора.

Благодаря много и на двама ви.

 

Също така не ми е ясно следното: имаме даден клас product и в него имаме поле (не съм сигурен това ли е термина) score. В учебника, който чета винаги правят функции като долната.

int product::get_score() const

{return score;

}

Та, въпросът ми е има ли смисъл от тях и ако да - какъв? 

Всичко най-най ;)

Редактирано от rusrusrus (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Също така не ми е ясно следното: имаме даден клас product и в него имаме поле (не съм сигурен това ли е термина) score. В учебника, който чета винаги правят функции като долната.

int product::get_score() const

{return score;

}

Та, въпросът ми е има ли смисъл от тях и ако да - какъв?

Много добър въпрос, за съжаление обаче, отговорът не е простичко изречение, а доста обширна тема. Все пак:

Казва се член-променлива на класа, но за мен и поле е добре.

Издъно погрешно е да се слагат get и set методи в клас, без много добра причина. Това, че в учебник слагат такива на всеки клас, е направо престъпление и авторът трябва да се разстреля (в кръга на шегата).

Идеята на класовете е капсуловане на определена информация и методите за работа с нея в еднороден и затворен обект. Затворен. Този, който употребява класа трябва да знае максимално малко за начина, по който работи класа отвътре. Това позволява разработката на класа и на неговия потребител да върви паралелно и независимо, като единственото което двамата знаят е интерфейса помежду си. get и set методите обикновено (99% от случаите) се ползват грешно и нарушават капсуловането на класа, изнасяйки ненужна информация.

Пример. (импровизация) Правиш клас, който използва вътре за нещо си масив, който никому на вън не трябва за нищо. За край на масива ползваш нулево поле. Имаш си get метод който връща масива. Някой си, ползва твоя клас и работи в Индия. Двамата пращате ъпдейти независимо на трети, който ползва всичко заедно. Твоя човек в Индия, знае за метода и за масива, и се мисли за много хитър, взема масива чрез гет метода и го редактира изотзад, без класа ти да знае, щото му е по-лесно отколкото да ползва правилните методи.. Ти обаче измисляш някакъв по-готин алгоритъм и решаваш, че масива вече няма да е нулево завършващ, а ще си имаш променлива за край. Правиш спешен ъпдейт на крайния клиент, че му трябва за утре и... Познай какво се случва, като пуснеш тестовете. Или недай си Боже директно да пратиш ъпдейта, знаейки че няма как нещо да се счупи, щом не си променял интерфейса на класа и си изтествал всичко твое.

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Благодаря много, за обширния отговор. Имам и още един въпрос.Кога се използва в даден клас указател към обект от самия клас.Например с горния клас да имаме product * pointer. Може би, ако имаме навързани product client1 , product client2  и т.н. и ако данните на един зависят от данните на предходния или нещо такова? Веднъж бях питал асистентката и май ми беше казала нещо за памет (май беше по този въпрос това) , ама нещо не я разбрах.

И още един въпрос. Когато искам да създам динамична памет примерно чрез:

int * pointer = new int[5]; Така създавам указател, който сочи към първия елемент на тази памет.Въпросът ми е обаче може ли още при използването на new да задам на елементите в този масив стойност ? Например от 1 до 5 ? Ако е за един елемент ми е ясно ще стане int *pointer =  new int(200) ; примерно обаче , когато имаме масив как става номера?

Та ще се радвам, ако препоръчате някой учебник по C++.

Всичко най-най ;)

Редактирано от rusrusrus (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Имам и още един въпрос.Кога се използва в даден клас указател към обект от самия клас.Например с горния клас да имаме product * pointer. Може би, ако имаме навързани product client1 , product client2  и т.н. и ако данните на един зависят от данните на предходния или нещо такова? Веднъж бях питал асистентката и май ми беше казала нещо за памет (май беше по този въпрос това) , ама нещо не я разбрах.

Хмм. Може да се използва за ужасно много неща. Основно, обаче се използва за реализиране на връзките в различни динамични структури от данни - свързани списъци, дървета, графове... Примерно, в един свързан списък, връзката на всеки от възлите в списъка със следващия може да се (и обикновено се) прави с указател към него. За дърво или граф, може във всеки възел да имаш дори списък с указатели към следващите възли (защото може да са неопределен брой).

И още един въпрос. Когато искам да създам динамична памет примерно чрез:int * pointer = new int[5]; Така създавам указател, който сочи към първия елемент на тази памет. Въпросът ми е обаче може ли още при използването на new да задам на елементите в този масив стойност ? Например от 1 до 5 ? Ако е за един елемент ми е ясно ще стане int *pointer =  new int(200) ; примерно обаче , когато имаме масив как става номера?

Не може директно. При използване на опрератора new[] се вика конструкторът по подразбиране на всеки един създаден обект, в случая констуктрът на int не задава стойност. Трябва да си инициализираш масива сам.

Та ще се радвам, ако препоръчате някой учебник по C++.Всичко най-най ;)

Използвайте търсачката в раздела.

Редактирано от flare (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Регистрирайте се или влезете в профила си за да коментирате

Трябва да имате регистрация за да може да коментирате това

Регистрирайте се

Създайте нова регистрация в нашия форум. Лесно е!

Нова регистрация

Вход

Имате регистрация? Влезте от тук.

Вход

×

Информация

Поставихме бисквитки на устройството ви за най-добро потребителско изживяване. Можете да промените настройките си за бисквитки, или в противен случай приемаме, че сте съгласни с нашите условия за ползване.