Przeciążanie operatorów. Kilka pytań.

Przeciążanie operatorów. Kilka pytań.
bajos
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:UwUdź
  • Postów:267
0

Witajcie,

Trzeba się w końcu nauczyć przeciążanie operatorów. Czytałem jakieś tam kursy (w tym ten na 4p). Nie mam pojęcia czym się różni w przeciążaniu operatorów, że typ zwracany/argumenty jest referencją lub nie i czym się różni const& od zwykłego &. Co to zmienia?


128 postów [25.06.2015r. 21:03]
twonek
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 2 lata
  • Postów:2500
1

czym się różni const& od zwykłego &

Kopiuj
void f(int& a)
{
    a = -11;	
}

void g(const int& a)
{
    a = -33;
}

void h(int a)
{
    a = 5;
}

g się nie skompiluje, bo a jest referencją na stałą, więc nie możesz jej modyfikować. h praktycznie nic nie robi, bo a jest kopią tego argumentu, który podałeś do funkcji.

Nie mam pojęcia czym się różni w przeciążaniu operatorów, że typ zwracany jest referencją

Jeśli typ zwracany nie jest referencją, to znaczy że jest nowym obiektem. A co najważniejsze obiektem tymczasowym, przez co np. taki kod nie przejdzie:

Kopiuj
x = y = z = w;

W tym przypadku potrzebujesz, żeby wynik x = y był referencją, dzięki czemu możesz przypisać do niego z. A potem do wyniku tego przypisać w.

bajos
@twonek, a mogę zawsze zwracać referencję czy są przypadki, że nie można bo coś będzie źle działać? Bo jak jest referencja to oszczędność pamięci (może niewielka ale zawsze). A jeśli jako prawy operand (?) operatora podam zmienną, która nie będzie const to nie ruszy?
twonek
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 2 lata
  • Postów:2500
0

a mogę zawsze zwracać referencję czy są przypadki, że nie można bo coś będzie źle działać?

Jak masz

Kopiuj
c = a + b

to raczej powinieneś tworzyć nowy obiekt. No bo jeśli zwracasz referencję powiedzmy do a (żeby nie było wątpliwości, nie możesz zwracać referencji do tymczasowego obiektu, jak referencja to tylko do czegoś istniejącego - w przypadku x = y modyfikujesz x i zwracasz referencję do niego), wyobraź sobie takie coś:

Kopiuj
c = a + b;         // dodaje b do a, a potem zwraca referencję do a
c = nowa_wartosc;         // ups, a teraz też ma nowa_wartosc

A jeśli jako prawy operand (?) operatora podam zmienną, która nie będzie const to nie ruszy?
No taka jest idea const, do tego służy.

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
0
bajos napisał(a):

Witajcie,

Trzeba się w końcu nauczyć przeciążanie operatorów. Czytałem jakieś tam kursy (w tym ten na 4p). Nie mam pojęcia czym się różni w przeciążaniu operatorów, że typ zwracany/argumenty jest referencją lub nie i czym się różni const& od zwykłego &. Co to zmienia?

A po co? to jest taki błyszczący feature jeżyka, na który rzucają się wszyscy początkujący.
Moja rada opanuj dobrze język, napisz kilka programów z kodem powyżej 200 linii i dopiero wtedy wróc do tematu przeciążania operatorów. Wtedy okaże się, że temat jest prosty.

To samo dotyczy wielowątkowości (jednak tu próg wymaganych minimalnych umiejętności jest znacznie wyższy).


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
bajos
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:UwUdź
  • Postów:267
0

@twonek,

g się nie skompiluje, bo a jest referencją na stałą, więc nie możesz jej modyfikować.
a tutaj http://cpp0x.pl/dokumentacja/standard-C++/Przeciazanie-operatorow/operator/1045 jest dobrze, a przecież

Kopiuj
 TypDanychT wartosc; 

nie jest stałą?


128 postów [25.06.2015r. 21:03]
twonek
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 2 lata
  • Postów:2500
0

Nie widzę żadnego powiązania między moim zdaniem a tym co napisałeś.

Nie widzę żadnej stałej w tym kodzie, który pokazałeś. Dlaczego w ogóle myślisz, że zwykła zmienna jest stałą?

Beznadziejny przykład w tym kursie, bo żadnego przypisania tam nie ma.

bajos
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:UwUdź
  • Postów:267
0

Napisaem sobie:

Kopiuj
 
/* .hpp */
#ifndef LINEPROCESSOR
#define LINEPROCESSOR

#include <string>

class LineProcessor {
protected:
    std::string source;
    unsigned int pointer;
public:
    explicit LineProcessor();
    explicit LineProcessor(std::string &str);
    std::string readTo(char chars[]);
    std::string readToBetween(char pairs[]);

    LineProcessor& operator=(const std::string &str);
};

#endif // LINEPROCESSOR

/* KONIEC .hpp*/
/* .cpp */

LineProcessor& LineProcessor::operator=(const std::string &str)
{
    source = str;
    pointer = 0;
    return *this;
}
/* KONIEC .cpp*/

/* Tak wyglada uzycie*/
LineProcessor lineProc();
lineProc = "linia1234xyz";                 // linia 11

qDebug() << lineProc.readTo("24y");  // linia 13

QtCreator pokazuje takie bledy:

Kopiuj
/home/patryk/projekty/BennuModelEditor/LoadingThread.cpp:11: błąd: assignment of function 'LineProcessor lineProc()'
     lineProc = "linia1234xyz";
              ^
/home/patryk/projekty/BennuModelEditor/LoadingThread.cpp:11: błąd: cannot convert 'const char [13]' to 'LineProcessor()' in assignment

/home/patryk/projekty/BennuModelEditor/LoadingThread.cpp:13: błąd: request for member 'readTo' in 'lineProc', which is of non-class type 'LineProcessor()'
     qDebug() << lineProc.readTo("24y");
                          ^

Wyglada na to ze chce wywolac konstruktor zamiast przeciazyc operator;

// PS. Jak wylaczyc alt jako klawisz skrotu do menu bar w Unity? Nie moge uzyc polskich znakow.


128 postów [25.06.2015r. 21:03]
edytowany 3x, ostatnio: bajos
twonek
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 2 lata
  • Postów:2500
1
Kopiuj
LineProcessor lineProc();

Tutaj deklarujesz funkcję o nazwie lineProc, która przyjmuje 0 parametrów i zwraca obiekt typu LineProcessor.
To co chciałeś osiągnąć to:

Kopiuj
LineProcessor lineProc;

Ogólnie reguły parsowania w C++ mówią, że jeśli można coś traktować jako deklarację funkcji, to właśnie tak zostanie traktowane. To jest jeszcze bardziej porypane jeśli bierze się pod uwagę, że nazwa funkcji w pewnych sytuacjach jest opcjonalna, więc

Kopiuj
SomeClass x(LineProcessor())

może być traktowane jako funkcja o nazwie x, która zwraca obiekt SomeClass, a przyjmuje jako parametr funkcję (bez nazwy) która zwraca LineProcessor i przyjmuje 0 parametrów.

Po więcej szczegółów możesz googlować "the most vexing parse c++".

kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Łódź
  • Postów:1402
0

jak chcesz wywołać:

Kopiuj
lineProc.readTo("24y");

to deklaracja winna wyglądać:

Kopiuj
std::string readTo(const char *chars);

natomiast linia 11 wymaga rzutowania.


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)