C++/ Klasy, konstruktory, dziedziczenie - do sprawdzenia

0

Cześć,
mam do napisania dość trudny jak dla mnie i przede wszystkim skomplikowany program w C++, nie podołałem wszystkim poleceniom, a i te które udało mi się wykonać mogą być wykonane błędnie. Jestem otwarty na Wasze propozycje jak i uwagi dotyczące błędów które pewnie są :)
**
Mam problem z punktami pogrubionymi **

Co to znaczy że parametry konstruktora inicjują zmienne ? Czy to znaczy że mam parametry w ciele konstruktora po prostu przypisac do zmiennych i to bedzie ta INICJACJA ?

Mam dość długie polecenie:

Do alokowania pamięci można użyc tylko operacji new/delete;
Do wyświetlania i wczytywania tylko zmiennych cin/cout
W każdym zadaniu należy pamiętac o dołączeniu niezbędnych plików nagłowkowych

DEKLARACJE
Poniższe zadanie ma składać się z trzech plików. Deklaracja klasy ma być napisania w pliku*.h, a definicje metod klasy oraz definicja funkcji main w dwóch różnych plikach *.cpp.

  1. Stworz klase Csmietnik posiadającą następujące pola i funkcje:
  2. prywatne pole A typu int,
  3. prywatne pole B typu float.
  4. 15-elementowa chroniona tablice znakow C.
  5. publiczny wskaznik D na typ short,
  6. publiczną statyczną skłądową E typu long (pole ma być zainicjowane wartością 0)
  7. chronioną stałą F typu short,
    **7. **publiczny konstruktor bezparametrowy inicjujący zmienne A, B, C, D, F odpowiednio liczbami 1, 2.5, piętnastoma literami „a” (należy użyc petli), NULLem, -13.
    **8. **chroniony konstruktor dwuparametrowy – parametry inicjują zmiene A i B, tablica C pozostacje niezainicjowana, zmienna D ma być inicjowana NULLem, zmienna F wartościa -13.
    **9. **publiczną funkcję wyswietl() wypisującą w jednej linii zmiene A, B, E, F i wszystkie komorki tablicy C. Wartosci maja być oddzielone spacjami.
    **10. **Publiczny jednoparametrowy konstruktor który dla wskaznika D tworzy tablice shortow o rozmiarze zadanym w parametrze i wypelnia ja kolejnymi liczbami calkowytmi (należy uzyc petli) poczynajac od wartosci -5 (czyli -5, -4, -3, -2, -1, 0, 1, 2...)
    11. Napisz funkcje ALADEEN w której utworzysz automatyczna 10-elementowa tablice elementow Csmietnik a następnie dla kazdego elementu wywolasz metode wyswietl().

PLIK Z DEKLARACJAMI – conio.hpp

#ifndef conio_hpp
#define conio_hpp

class Csmietnik{

public:
	CSmietnik *D= new short; // nie wiem czy to jest dobrze
	static long E = 0; 
	Csmietnik(); // 1 konstruktor bezparametrowy
	void wyswietl();
	Csmietnik (int x); // drugi jednoparametrowy kostruktor, czy moge nazwac go tak samo ? 
        ~Csmietnik();
        ~Csmietnik(int x);
private:
	int A;
	float B;
protected:
	tab[15]={C};
	short int F;

};


#endif

 

PLIK Z DEFINICJAMI – conio.cpp

#include ”conio.hpp”

using namespace std;

void ustaw (int x, float y, lng int j, short int i, tab[j])  //  będzie porzadkowac elementy do metody wyswietl, tak zeby nie pomieszaly sie typy
{
x=A;
y=B;
j=E;
i=F;
tab[j]=tab[15]={C};

void wyswietl(int x, float y,  long int j, short int i, tab[j])
{
     cout << x << y << j << i << j << endl;
}

// moge od razu ot tak napisac nazwe konstruktora i zostanie on rozpoznany ? w stylu: 

Csmietnik( ) // bezparametrowy, znaczy się że nie może przyjmować żadnych argumentów ? Tak ? 
{
   int a[15], i;
   for(i=0; i<15; i++)
   {
       a[i]="C";  // **to nie moze sie udac, bo w ten sposob przypisuje kazdej komorce od 0 do 15, licząc o jeden wzwyż, przypisuje literę, a zmienna i jest typu int, więc chyba trzeba by wykonać rzutowanie ? Prawda ? JEśli tak to jak? **
    }

0

Tutaj w zasadzie niewiele rzeczy jest dobrze. Z jakich podręczników uczysz się C++?

0

Z roznych skryptow, mozesz pokazac gdzie dokladnie "nie jest dobrze" ?

0

W co drugiej linijce. Zaopatrz się w porządną książkę o programowaniu w C++. Nawet jeżeli ktoś ci pomoże i napisze ten kod od nowa to tak naprawdę niewiele ci to da. Można w ten sposób poprzez analogię nauczyć kogoś użycia funkcji, klasy ze standardowej biblioteki czy funkcjonalności języka, ale nie całej jego składni.

Co do książki: może być oklepana Symfonia C++ Standard (szukaj jak najnowszego wydania). Inne tytuły możesz znaleźć na tym forum w innych wątkach (użyj wyszukiwarki).

0

Chyba podziękuję za takie porady. Jestem zaznajomiony z dobrymi źródłami z tematyki programowania, ale nie mam jeszcze obycia by scalić moje nikłe doświadczenie i pisać bezbłędnie, dlatego umieściłem na forum ten temat licząc że ktoś mnie poprawi, wykazałem się jakims wkładem czym pokazałem że nie jestem leniem i za bardzo nie rozumiem dlaczego spotykam się z takimi odpowiedziami, nawet sformułowanie: "w co drugiej linijce", jest chybione, bo nie wiadomo od której mam zacząć liczyć...

3

Nie trzeba mieć doświadczenia, żeby poznać podstawową składnię języka programowania. Trzeba tylko posiedzieć z podręcznikiem. Nie przekonasz mnie i nikogo na tym forum, że jesteś dobrze zaznajomiony z dobrymi źródłami deklarując wskaźnik w taki radosny sposób: CSmietnik *D= new short;

Ale niech będzie, mam jedną radę: zacznij od początku i po zmianie chociaż jednej linijki kodu próbuj go kompilować. Jeżeli nie uda się, wróć do podręcznika, który omawia rzeczy, które wykorzystałeś w tej jednej linijce, popraw je i skompiluj jeszcze raz. Jeżeli się uda - przejdź do następnego punktu z zadania.

0

Jak napisał kolega @Rev, błędów jest sporo. Nie bardzo wiem od czego zacząć. Jeśli jesteś zaznajomiony z dobrymi źródłami to albo nie są związane z C++ albo po prostu są pisane zbyt ogólnie, bo błędów masz zbyt dużo, jakby brakowało podstaw. Czy chcesz żeby napisać Ci gotowy kod, czy chcesz zrozumieć o co chodzi i napisać samemu?

0

Oo.. i to już w jakiś sposób pomogło. Źle zdefiniowany wskaźnik. I wiem co mam poprawić.

Lena(R)> czytanie ze zrozumieniem -.-, przecież nigdzie nie napisałem że chce uzyskać gotowy kod źródłowy, mowa tylko o wskazanie błędów. Kompilator jest dość małomówmy...
"Nie bardzo wiem od czego zacząć. " - to może w ogóle proszę nie zaczynaj... może i to chamskie zachowanie z mojej strony, jako że jestem zapewne nieporównywalnie gorzej zaznajomiony z C++, ale porady mentorskiej udzielil mi już Rev.

1
CSmietnik *D= new short; // nie wiem czy to jest dobrze

Wskaznika na short nie przypiszesz do wskaznika na CSmietnik. Nawet jesli Ci sie uda to skompilowac, to rozwalisz caly obiekt i skonczysz marnie z Access Violation.

~Csmietnik();
~Csmietnik(int x);

Klasa moze miec tylko jeden, bezparametrowy destruktor.

tab[15]={C};

Czym jest C?

void ustaw (int x, float y, lng int j, short int i, tab[j])  //  bedzie porzadkowac elementy do metody wyswietl, tak zeby nie pomieszaly sie typy
{
x=A;
y=B;
j=E;
i=F;
tab[j]=tab[15]={C};

Zaczne od komentarza, ktory i tak jest jednym z mniejszych WTF-ow w tej funkcji. Czy zdajesz sobie sprawe, ze C++ jest silnie statycznie typowany? Typy nie moga sie pomieszac.
Brak klamry zamykajacej jest tak oczywisty, ze nawet nie powinienem o tym wspominac.
Skad wolna funkcja ma wiedziec, czym sa A, B, C, D, E, F?

Csmietnik( ) // bezparametrowy, znaczy sie ze nie moze przyjmowac zadnych argumentów ? Tak ? 
{
   int a[15], i;
   for(i=0; i<15; i++)
   {
       a[i]="C";
    }

Znow brak klamry. Jesli chcesz implementowac jakas metode klasy, powinienes wyraznie zaznaczyc, ze metoda z tej klasy pochodzi, czyli Csmietnik::Csmietnik(). Stringa do inta w ten sposob nie powinienes przypisywac. Byc moze chodzi ci o znak ASCII C? W takim wypadku stosuj pojedyncze apostrofy.

Nie chce mi sie dalej punktowac, a to zaledwie lizniecie tematu zalosnosci tego kodu. Przede wszystkim: probowales to skompilowac? Bo pisanie na sucho z tutoriali jest tak wysoce bezsensowne, ze az mi sie slabo robi. Zainstaluj VC++ Express albo Code::Blocks i kompiluj, probuj sam uruchomic to co napisales, a nie bezmyslnie kopiowac albo przepisywac, do tego robiac w cholere literowek.

1

Nie daję gwarancji, że poniższy kod jest dobry, bo był pisany na szybko.

CSmietnik.h

class CSmietnik{
 
public:
    short *D;
	static const long E = 0;

	CSmietnik();
	CSmietnik(short *d);

	void wyswietl();

private:
	int A;
	float B;

protected:
	char C[15];
	static const short F = -13;

	CSmietnik(int a, float b);
 
};

CSmietnik.cpp

#include "CSmietnik.h"
#include <iostream>

using namespace std;

CSmietnik::CSmietnik()
{
	A = 1;
	B = 2.5;
	for(int i = 0; i < 15; ++i)
	    C[i] = 'a';
	D = NULL;
}

CSmietnik::CSmietnik(int a, float b)
{
	A = a;
	B = b;
	D = NULL;
}

void CSmietnik::wyswietl()
{
	cout << A << " " << B << " " << E << " " << F << " ";
	for(int i = 0; i < 15; ++i)
		cout << C[i] << " ";
	cout << endl;
}

main.cpp

#include "CSmietnik.h"
#include <iostream>

using namespace std;

void ALADEEN()
{
	CSmietnik Smietnik[10];
	for(int i = 0; i < 10; ++i)
		Smietnik[i].wyswietl();
}

int main()
{
	ALADEEN();

	return 0;
}
0

Stworz klase Csmietnik posiadajaca nastepujace pola i funkcje:

  1. prywatne pole A typu int,
  2. prywatne pole B typu float.
  3. 15-elementowa chroniona tablice znakow C.
  4. publiczny wskaznik D na typ short,
  5. publiczna statyczna skladowa E typu long (pole ma byc zainicjowane wartoscia 0)
  6. chroniona stala F typu short,
  7. publiczny konstruktor bezparametrowy inicjujacy zmienne A, B, C, D, F odpowiednio liczbami 1, 2.5, pietnastoma literami „a” (nalezy uzyc petli), NULLem, -13.
  8. chroniony konstruktor dwuparametrowy – parametry inicjuja zmiene A i B, tablica C pozostacje niezainicjowana, zmienna D ma byc inicjowana NULLem, zmienna F wartoscia -13.
  9. publiczna funkcje wyswietl() wypisujaca w jednej linii zmiene A, B, E, F i wszystkie komorki tablicy C. Wartosci maja byc oddzielone spacjami.
  10. Publiczny jednoparametrowy konstruktor który dla wskaznika D tworzy tablice shortow o rozmiarze zadanym w parametrze i wypelnia ja kolejnymi liczbami calkowytmi (nalezy uzyc petli) poczynajac od wartosci -5 (czyli -5, -4, -3, -2, -1, 0, 1, 2...)

Wspomoc Cie moge definicja klasy, bo czytanie polecen ze zrozumieniem masz na podobnym poziomie co C++.

// csmietnik.h
class Csmietnik
{
public:
    static long E; // punkt 5.
    
    Csmietnik(); // punkt 7.
    Csmietnik(int size); // punkt 10.
    void wyswietl(); // punkt 9.
    
protected:
    char C[15]; // punkt 3.
    const short F; // punkt 6.
    
    Csmietnik(int a, float b); // punkt 8.
    
private:
    int A; // punkt 1.
    float B; // punkt 2.
    short* D; // punkt 4.
};

// csmietnik.cpp
long Csmietnik::E = 0;
// ...
0

Ok, naniosłem poprawki. Myślę że większość z nich jest już bez zarzutu, linie które uległy zmianom w porównaniu do poprzedniej wersji są pogrubione.

Plik z deklaracjami conio.hpp

#ifndef conio_hpp
#define conio_hpp

class CSmietnik{
   
   // ZAUWAZYLEM ZE, funkcje ALADEEN(), wyswietl() beda korzystaly z skladowych prywatnych i chronionych klasy CSmietnik, więc chyba wypadało by je zaprzyjaźnić

   **friend void ALADEEN();
   friend void wyswietl(char);** // nie wiem jaki typ zmiennych powinna przyjmowac funkcja wyswietl jako argument, skoro beda to znaki to przyjalem char
   
   public:
   
   short * D; 
   **static long CSmietnik::E=0;  **
   CSmietnik() // konstruktor bezparametrowy
   CSmietnik(*D)  // konstruktor który dla wskaźnika D tworzy tablicę shortow
   void wyswietl();
   
   private:
   int A;
   float B; 
   
   protected:
   
   **char tablica_znakow[15]={"C"}; **// tablica znakow C, jak dla mnie oznacza tablicę zapełnioną w całości znakami C, ewentualne uwagi mile widziane
   short F;
   CSmietnik(int, float); // konstruktor dwuparametrowy, parametry inicjują zmienne A i B, typ odpowiednio: int i float.


#endif

Plik z definicjami conio.cpp


#include "conio.hpp"

**void wyswietl (char A) // czy jesli podamy funkcji więcej argumentów niż jeden to nie wyświetli ich ? Jak mam określić "nieznaną" liczbę argumentów które ma wyświetlić ta funkcja, podobny problem mam z funkcjami get i set
{
   cout << A << endl; **
} 

**void ALADEEN
{
char Smietnik[10]={A, B, C tu wypisuje te składowe...} //tak mi sie przynajmniej wydaje
int i;
for(i=0; i<10; i++)
{
   Smietnik[i].wyswietl;
}**

Nad 10 sie jeszcze glowie,

Jeśli jest jakaś poprawa i zrodlo nie wyglada juz na jakis pseudokod, postaram sie wrzucic main. Tak zeby nie robic tutaj zamieszania.

// **PRZEPRASZAM NIE ZAUWAZYLEM ZE DODALISCIE SWOJE ODPOWIEDZI ** ale posta nie bede kasowal na razie :)

0
  1. Dlaczego wyswietl() jest zaprzyjazniona? To powinna byc normalna metoda skladowa.
  2. Dlaczego wyswietl() przyjmuje jakis parametr? Nie ma takiej potrzeby, chyba ze chcialbys podawac np. strumien, do jakiego ma pisac.
  3. Tablica znakow C to char C[], nic innego. Wedug standardowej nomenklatury <typ> <nazwa-zmiennej>.
  4. Deklaracja 'E' jest nieprawidlowa, spojrz na moj poprzedni post.
  5. F ma byc stala, wyraznie jest to napisane w zadaniu.
  6. char Smietnik[10]={A, B, C tu wypisuje te składowe...} - WTF? Do tablicy 10 znakow chcesz przypisac cos z d**y, a potem jeszcze w petli dla kazdego chara chcesz na nim wywolac metode (i do tego zapomniales o nawiasach).
    Wciaz jest to masakra, przykro mi. Proponuje, zebys kolejnego posta wrzucil z kodem, ktory chociaz sie kompiluje.
0

1. Dlaczego wyswietl() jest zaprzyjazniona? To powinna byc normalna metoda skladowa.

Bo będą ją używał poza "ciałem" klasy. Patrz punkt 11.

2. Dlaczego wyswietl() przyjmuje jakis parametr? Nie ma takiej potrzeby, chyba ze chcialbys podawac np. strumien, do jakiego ma pisac.

Chciałem po prostu żeby do funkcji można było wpisać jakiś argument, tak by potem ten argument został przez nią wyświetlony.
Czy jeśli mam zrezygnować z funkcją z parametrem, to poprawne funkcja powinna wyglądać tak:

 
void wyswietl()
  {
   cout<<tab<<endl;
  } 

To masz na myśli ?

3. Tablica znakow C to char C[], nic innego. Wedug standardowej nomenklatury <typ> <nazwa-zmiennej>.

Dzięki, myślałem że trzeba ją zapełnić, pierwszy raz sie z tym spotkalem.

4. Deklaracja 'E' jest nieprawidlowa, spojrz na moj poprzedni post.

Tu chyba we dwójkę popełniliśm ten sam błąd, tak wynika ze wskazówki Shaloma ;) Ok, rozumiem, czysta deklaracja w .hpp, a potem w .cpp już będę mógł jej przypisać wartość.

5. Nie z d**y tylko z pamieci :) Tak jak w poleceniu mam utworzyc 10 elementowa tablice, to chyba dobrze. Ma zawierac elementy CSmietnik, więc je po prostu wpisuje ręcznie, każdy jeden z osobna ? Potem dla kazdego chce wywolac metode, bo tak jest w poleceniu.

Wciaz jest to masakra, przykro mi. Proponuje, zebys kolejnego posta wrzucil z kodem, ktory chociaz sie kompiluje.

Błąd semantyczny, jeżeli umiał bym napisać samemu kod który "chociaż" by się kompilował to nie zakładał bym tego tematu...

Wciaz jest to masakra, przykro mi. Proponuje, zebys kolejnego posta wrzucil z kodem, ktory chociaz sie kompiluje.

0
aladeen napisał(a):

1. Dlaczego wyswietl() jest zaprzyjazniona? To powinna byc normalna metoda skladowa.
Bo będą ją używał poza "ciałem" klasy. Patrz punkt 11.

Bedziesz ja wywolywal na rzecz obiektu, dlatego ma to byc metoda skladowa.

aladeen napisał(a):

5. Nie z d**y tylko z pamieci :) Tak jak w poleceniu mam utworzyc 10 elementowa tablice, to chyba dobrze. Ma zawierac elementy CSmietnik, więc je po prostu wpisuje ręcznie, każdy jeden z osobna ? Potem dla kazdego chce wywolac metode, bo tak jest w poleceniu.

Czy rozumiesz idee typowania? Probujesz przypisac jakies niestworzone wartosci do tablicy znakow. Powinna to byc tablica obiektow CSmietnik, czyli CSmietnik tab[10].

Widze, ze nie masz za bardzo pojecia, jak powinno to zostac zrobione. Szczerze mowiac, poddaje sie i dam ci dzialajacego gotowca, zastanow sie nad roznicami miedzy tym, co napisales ty, a co ja.

// smietnik.h
#pragma once

class CSmietnik
{
public:
    static long E;
 
    CSmietnik();
    CSmietnik(int size);
    ~CSmietnik();
    void wyswietl();
 
protected:
    char C[15];
    const short F;
 
    CSmietnik(int a, float b);
 
private:
    int A;
    float B;
    short* D;
};

void ALADEEN();
// smietnik.cpp
#include <iostream>
#include "smietnik.h"

long CSmietnik::E = 0;

CSmietnik::CSmietnik() : A(1), B(2.5), D(NULL), F(-13)
{
    for (int i = 0; i < 15; ++i)
        C[i] = 'a';
}

CSmietnik::CSmietnik(int a, float b) : A(a), B(b), D(NULL), F(-13)
{
}

CSmietnik::CSmietnik(int size) : D(new short[size]), F(0)
{
    for (int i = 0; i < size; ++i)
        D[i] = i - 5;
}

CSmietnik::~CSmietnik()
{
    delete[] D;
}

void CSmietnik::wyswietl()
{
    std::cout << A << ' ' << B << ' ' << E << ' ' << F;
    for (int i = 0; i < 15; ++i)
        std::cout << ' ' << C[i];
}

void ALADEEN()
{
    CSmietnik tab[10];
    for (int i = 0; i < 10; ++i) {
        tab[i].wyswietl();
        std::cout << "\n";
    }
}
// main.cpp
#include <iostream>
#include "smietnik.h"

int main()
{
    ALADEEN();
}
0

Nie spodziewałem się żeby ktoś mi napisał gotowca, ale muszę przyznać że bardzo na tym skorzystałem. Dziękuję.

Co do tego "obostrzenia" że w zadaniu nie ma dziedziczenia, to jakoś dziwnie forum skróciło mi posta ;/ Bo mam jeszcze drugie zadanie, ale za nim do niego dojdę muszę uporać się z tym na dole, a mam z nim kilka kłopotów.

  1. Zdefiniuj klasę Cpunkt, a wniej:
  2. Prywatne pole x i y typu double.
  3. Publiczny bezargumentowy konstruktor, ustawiajacypola x i y na 0.0
  4. publiczny dwuargumentowy konstruktor, przypisujacy wartosci parametrow do pol xi y
  5. publiczną funkcję operatorową dla operatora ==, która jako swoj argument (jawny argument, stojący z prawej strony operatora) przyjmuje referencję do Cpunkt. Funkcja zwraca wartość logiczną true jeśli porównywane „punkty” mają takie same współrzędne lub wartośc false jeśli ich współrzędne są różne.
// deklaracje.hpp

#pragma once

class CPunkt {

friend ostream& operator<< (ostream&,CPunkt const&); // deklaracja przyjazni

class &ref_CPunkt=ref_CPunkt // ustanawiam referencję, dobrze ? 

	private:
	
	double x, y;

	public:
	
        CPunkt(); // punkt 2
        ~CPunkt(); // punkt 2 
        CPunkt(double, double); // punkt 3
        bool operator==(&ref_CPunkt) // punkt 4

	protected:
};

3. Publiczny dwuargumentowy konstruktor, przypisujacy wartosci parametrow do pol x i y
Jak mam cos takiego stworzyc ?

 
CPunkt::CPunkt(double a, double b)
{
   double a = double CPunkt::x;
   double b = double CPunkt::y;
}

Dobrze ?

Jak trzeba zabrać się za czwarte polecenie ?

0
CPunkt::CPunkt(double a, double b)
{
   double a = double CPunkt::x;
   double b = double CPunkt::y;
}
 

WTF?! Nie uczyli tam jeszcze o liście inicjalizacyjnej?

CPunkt::CPunkt(double a, double b) :
  x(a),
  y(b) {
}
class &ref_CPunkt=ref_CPunkt // ustanawiam referencję, dobrze ?
bool operator==(&ref_CPunkt) // punkt 4

WTF?! Proszę, wyjaśnij co to wg Ciebie robi?

1

Wybacz, ale po prostu załamuję ręce. Dałem ci gotowca, żebyś zobaczył, jak właściwie powinna wyglądać struktura kodu. Nie mam zamiaru pozwolić ci zaliczyć kampanii wrześniowej, jeśli nawet nie masz bladego pojęcia o składni języka.

class CPunkt {
    friend ostream& operator<< (ostream&,CPunkt const&); // CO to jest i PO CO!? Nie ma tego w poleceniu
 
    class &ref_CPunkt=ref_CPunkt // W tym momencie czytam juz tylko z masochistycznej przyjemnosci; wytlumacz, co to ma byc?
private:
        double x, y;
        public:
 
        CPunkt(); // punkt 2
        ~CPunkt(); // PO CO tu destruktor!?
        CPunkt(double, double); // punkt 3
        bool operator==(&ref_CPunkt) // WTF!?
};
0

Nie cały rok, a semestr ;) Ponadto, to nie studiuję informatyki, ale czy tak czy tak, trzeba przysiąść.

rincewind- znamy się ?

Dzięki za pomoc, już tłumaczę o co chodziło.

class CPunkt {
    friend ostream& operator<< (ostream&,CPunkt const&); //  **faktycznie nie ma tego w poleceniu, to moja notatka**
 
    class &ref_CPunkt=ref_CPunkt


private:
        double x, y;
        public:
 
        CPunkt(); // punkt 2
        ~CPunkt(); // **Wzorowałem się na twoim kodzie**
        CPunkt(double, double); // punkt 3
        bool operator==(&ref_CPunkt) // **nawiązanie do punktu 4**
};

 

Ok, a więc... . W punkcie czwartym jest napisane: publiczną funkcję operatorową dla operatora ==, która jako swoj argument (jawny argument, stojący z prawej strony operatora) przyjmuje REFERENCJĘ DO CPUNKT. Funkcja zwraca wartość logiczną true jeśli porównywane „punkty” mają takie same współrzędne lub wartośc false jeśli ich współrzędne są różne.

Myslalem ze trzeba ja po prostu oddzielnie stworzyć. Nie wiem dokładnie jak zadeklarować ten argument by był REFERENCJĄ DO CPUNKT. Znam wskaźniki albo mi się wydaje, referencje są dość podobne, ale moim zamiarem było "zadeklarowanie" tej referencji, innymi slowy: tak by przypisać czemu odpowiada operator &ref_CPunkt, tak jak we wskaźnikach. Już wiecie skąd wziąłem taki głupi pomysł ? W poleceniu jest napisane że mam zrobić referencję do CPunkt, chodzi zapewne o kosntruktor (mysle ze to nie gafa).

Co do punktu drugiego. Czy taki konstruktor byłby wporządku ?


CPunkt::CPunkt()
	{
	double CPunkt::x==0;
	double CPunkt::y==0;
	}


 
1

To po kolei.

"publiczną funkcję operatorową dla operatora =="
Zacznijmy od tej części. Przede wszystkim Ty zdeklarowałeś ją w sekcji private a miała być w public. Pewnie już przeczytałeś/wiesz, że przeciążenie operatorów w C++ realizują zwyczajne funkcje, które tylko odpowiednio się nazywają. Wiesz pewnie, że jeżeli chodzi o operator == to typem zwracanym ma być tym bool. Chodzi nam bowiem o taką operację:

CPunkt punkt1;
CPunkt punkt2;

// ... jakis kod
// I teraz np:
if (punkt1 == punkt2) // ...

No dobrze. Dalej jest mowa o jakichś stronach i argumentach: "która jako swoj argument (jawny argument, stojący z prawej strony operatora) przyjmuje referencję do CPunkt". Oczywiste jest, że operator == jest dwuargumentowy. Skoro operator będzie funkcją składową to jednym jego argumentem jest obiekt tej klasy, którą właśnie definiujesz. Drugim będzie w takim razie argument tej funkcji, którą masz zadeklarować. Mam nadzieję, że to wiesz? To właśnie ten argument po prawej. Jaki jest jego typ? W kodzie powyżej widać, że oba argumenty są typu CPunkt. Napisałbyś pewnie wtedy tak:

bool operator==(CPunkt prawy);

I takie coś oczywiście zadziała. Mam nadzieję, że do tej pory rozumiesz co się dzieje? Autor zadania chce, aby tym argumentem było jednak coś innego. Co? Otóż "referencja do CPunkt". A Co mamy teraz? Argument typu CPunkt. Czyli coś trzeba zmienić. Referencję oznacza się & (tak jak wskaźnik *). Skoro więc wiesz, że referencje to coś podobnego do wskaźników możesz tę wiedzę wykorzystać i po prostu zmienić to tak:

bool operator==(CPunkt &prawy);

I to wszystko. Teraz pytaj dlaczego tak a nie inaczej. ;-) To nie może być tak, że "referencja to coś podobnego do wskaźników" powinieneś dobrze znać ten koncept. Przede wszystkim musisz nauczyć się swobodnego posługiwania się składnią.

0

Może wyjdę na idiotę, ale takie są uroki zdobywania wiedzy ;)

Mówisz że operator "==" jest dwuargumentowy, a więc wyobrażam sobie go w następujący sposób:

 bool operator==(typ_zmiennej+nazwa1, typ_zmiennej+nazwa2);

Tymczasem, u Ciebie mamy jeden argument ? Zakładamy że jednym z argumentów na pewno będzie obiekt tej klasy, ok, bez obiektu nie dostaniemy się do zmiennych, o to chodzi ?

Jednym argumentem będzie jakaś zmienna typu CPunkt, drugim będzie ta referencja, tak ?

Dlaczego przy referencji nie pokazałes na co ona ma wskazywać, tj. &referencja musi być czemuś przypisana, jakieś zmiennej, obiektowi etc. np. &referencja=bool i ? Nieprawdaż ?

Dzięki za pomoc !

By the way, czy ten konstruktor nawiazujacy do 2 punktu jest poprawny ?

 
CPunkt::CPunkt()
        {
        double CPunkt::x==0;
        double CPunkt::y==0;
        }
 


1

@Endrju dobrze mówi, jeszcze co do składni:

CPunkt::CPunkt()
{
    double CPunkt::x==0;
    double CPunkt::y==0;
}

Powinieneś wiedzieć, że typ podaje się przy deklaracji zmiennej, potem typ jest już znany. Dlatego przy przypisaniu do istniejącej zmiennej nie podajesz typu – w taki sposób, w jaki to tu zrobiłeś, robisz deklarację nowych zmiennych, co w tym konkretnym przypadku nie ma szans się skompilować.

1

Tymczasem, u Ciebie mamy jeden argument ? Zakładamy że jednym z argumentów na pewno będzie obiekt tej klasy, ok, bez obiektu nie dostaniemy się do zmiennych, o to chodzi ?

Jednym argumentem będzie jakaś zmienna typu CPunkt, drugim będzie ta referencja, tak ?

Dlaczego przy referencji nie pokazałes na co ona ma wskazywać, tj. &referencja musi być czemuś przypisana, jakieś zmiennej, obiektowi etc. np. &referencja=bool i ? Nieprawdaż ?

To po lewej stronie to będzie ten obiekt klasy, wewnątrz której definiujesz operator. Jakiś obiekt. Będziesz mieć przecież dostęp do wszystkich jego składowych jak w każdej funkcji składowej.

Ta referencja na nic nie pokazuje. Ona będzie pokazywać, jak ktoś wywoła funkcję, czyli użyje operatora.

if (punkt1 == punkt2) // ...

punkt1 to będzie ten obiekt, na rzecz którego zostanie wywołana funkcja operator==. Jego składowe będą tymi składowymi, do których normalnie możesz się odwoływać w każdej funkcji składowej. Natomiast w right czyli naszej referencji (argumencie będącym referencją), będzie referencja do obiektu punkt2.

Wydaje mi się, że powinieneś wrócić do jakiejś książki i zacząć naukę od podstaw.

0

O ja faktycznie błazenada z mojej strony. Po prostu myślałem że, ehh... nieważne. Pomyłka ze zmęczenia i pewnie z braku doświadczenia.
Ok zrozumiałem Twoje tłumaczenie doskonale. Zaraz przedstawię swą "radosną tworczosc"

Ale mam jeszcze jedno pytanie, mianowicie:
Składnia poniższa:

bool operator==(CPunkt &prawy); 

Jest dla mnie zrozumiała. Czyli potem możemy zacząć bawić się ifami ? Tj.
Czyli w zarysie chodzi mnie wiecej o takie coś ?

 

CPunkt punkt1; //deklaracje obiektów klasy CPunkt, prawda ?
CPunkt punkt2;

double x, y; // zadeklarowane juz wczesniej, ale tak tylko dla jasnosci

bool operator==(CPunkt &prawy); 

if (punkt1.x==punkt2.x) && if(punkt1.y==punkt2.y)
{
   return true;
}
else {
 return false;
}

0

Po zdefiniowaniu operatora == wystarczy to:

CPunkt a(1, 1);
CPunkt b(2, 2);

if (a == b)
    return true;
else
    return false;

Na tym polega przeciazanie – przeciazasz operator dla obiektu danej klasy. Nie musi cie obchodzic wewnetrzna struktura samej klasy – jesli implementuje operator porownania, uzywasz go tak samo, jak porownanie dla zwyklych liczb.

0

Powoli zaczynam łapać, przeciążeniem operatora można nazwać "implementację dodatkowych opcji/funkcji" do jego pierwotnego działania. Dobrze pojmuje ?
To co napisałem chyba nic nie ma wspólnego z przeciążeniem funkcji...
Bo tak na chłopski rozum sam operator porównania ==, nie mógł by porównać dwóch obiektów o zdefiniowanych polach, służy tylko porównywaniu jakiś pojedynczych zmiennych.

Jeszcze wrócę do samej definicji funkcji operatowej dla "==", bo za bardzo nie rozumiem.

Z konstrukcji moge wywnioskowac, że:

  1. funkcja składowa klasy = funkcja zawierająca obiekt tej klasy;

  2. bool operator to obiekt klasy CPunkt;

Drugim argumetem będzie argument funkcji operator, po prawej stronie

bool operator == (// czas na argumentu, najpierw jego typ: tj. CPunkt, a potem on sam)

referencja, operator referencji to ampersand, który jest poprzedzony tym na co wskazuje/referuje lub do czego wskazuje, a więc drugi argument:

CPunkt (CPunkt to obiekt na który wskazuje referencja), czyli np.

CPunkt & - referencja do CPunkt ? Tak ? Trochę mi się myli z typem.

Po ampersandzie wstawiamy nazwę tej referencji, która potem może zostać do czegoś "przypisana". Tak jak w przypaku wskaźników.

I tak potem mamy CPunkt & jestem_sobie_referencja i odczytujemy, referencja na CPunkt o nazwie jestem_sobie_referencja.

1

Tak se dziś odpowiadam w róźnych tematach ale ten obserwuję od jakiegoś czasu. Jak widze nowe posty to się uśmiecham. Dalej chłopaki walczą żeby się z Tobą jakoś uporać. Aż pomogę :D

Po kolei "przeciążeniem operatora można nazwać "implementację dodatkowych opcji/funkcji" do jego pierwotnego działania"
A co to pierwotne działanie. Jeśli chcesz to możesz dla operatora == zaprogramować pianie koguta a dla operatora < format dysku. Ale po części masz rację. To jest w pewnych przypadkach znacznie bardziej intuicyjne np. gdy masz typ liczby zespolonej Complex i zmienne tego typu a i b to znacznie czytelniej jest napisać a+ b niż a.plus(b).

Bo tak na chłopski rozum sam operator porównania ==, nie mógł by porównać dwóch obiektów o zdefiniowanych polach, służy tylko porównywaniu jakiś pojedynczych zmiennych.

Tak? :) A co gdy masz kod

Class Pies
{
   Color kolor;
   String imie;
bool operator ==( const Pies & inny );
}

To co stoi na przeszkodzie aby ciałem Twojego operatora == było

bool Pies::operator ==( const Pies & inny )
{
   if(this->imie == inny.imie && this->kolor == inny.kolor)
      return true
    else
   return false;
    
} 

Lecimy dalej.

  1. funkcja składowa klasy = funkcja zawierająca obiekt tej klasy;
    Źle. Funkcja składowa to funkcja która znajduje się w tej klasie. Może korzystać ze zmiennych obiektu ale nie musi.
Class pies
{
   Color kolor;
   String imie;

void hau();   // To jest funkcja składowa.

String getKolor()  // To też jest funkcja składowa
{
return kolor;
}

}

void Pies::hau() // To jest wciąż funkcja składowa. Niby jest poza klasą. Ale jest to definicja funkcji która jest zadeklarowana wewnątrz klasy.
{
cout<<"Hau";
}

void innaFunkcja() // Ta funkcja może se używać obiektów typu Pies ale nie jest składową...
{
Pies p;
p.hau();
}
 

Dalej

CPunkt & - referencja do CPunkt ? Tak ? Trochę mi się myli z typem.
Bardzo dobrze, że Ci się myli. Co to za referencja w ogóle?? :|

To jest referencja. Zmienna b.

int a = 5;
    int& b = a;
    b = 3 ;
    cout<<a; 

Ok. Czekam na kolejną rundę zmagań z Tobą. Zaczyna mnie to bawić :)

0

Malootki, czy nie jesteś przypadkowo megalomanem ?

Stworzyłem temat by zadawać pytania, jeśli rozśmiesza Cię poziom zadawanych pytań i lubisz "połechtać" swoje ego, to proszę nie w moim temacie.

I po co w tym pierwszym przykładzie, po co stosować this -> ? Mogło by chyba być bez this ?

0

Cóż, starałem się, ale to jak grochem o ścianę. Przecież ty nawet nie raczyłeś dotknąć książki czy jakiegokolwiek tutoriala. Nawet nie próbujesz poszukać czegoś na własną rękę oczekując, że zrobimy ci tu wykład z całego ulanego przez ciebie semestru. Jesteś w czarnej dupie z własnej winy, i nie starasz się tego zmienić.

Ja kończę z odpowiedziami w tym temacie. Ostatnie, co mogę dla ciebie zrobić, to polecić zapoznanie się z tym: http://cpp0x.pl/kursy/Kurs-C++/1 Chciałbym powiedzieć, że lekcje 24 i 25, ale przecież ty nawet zmiennych nie potrafisz deklarować. Więc jedź od początku. Powodzenia.

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