[C++]Ocena poprawności kodu

0

Mam napisać program w C++ implementujący parę operacji na obiektach klasy wektor dwuwymiarowy. Więc stworzyłem coś co się kompiluje i działa poprawnie i listning zamieszczam poniżej:

#include <iostream.h>
#include <math.h>

//---------------------------------------------------------------------------
class wektor
{
public:
wektor();
wektor(float,float);
wektor operator+(wektor);
void dlugosc(void);
void wypisz(void);

   private:
            float x,y;
            float norma;

};

wektor::wektor()
{
x = 0;
y = 0;
norma = 0;
}

wektor::wektor(float _x, float _y)
{
x = _x;
y = _y;
norma = 0;
}

wektor wektor::operator+(wektor w)
{
wektor wynik;

    wynik.x = x+w.x;
    wynik.y = y+w.y;

    return wynik;

}

void wektor::dlugosc(void)
{
norma = sqrt(xx+yy);
}

void wektor::wypisz(void)
{
cout << " [" << x << "," << y << "] ";
cout << "||w||=" << norma << endl;
}

//-------------------------------------------------------------------------
void main(void)
{
wektor w1(2,2), w2(3,3), w3;

    w1.dlugosc(); w1.wypisz();
    w2.dlugosc(); w2.wypisz();
    w3.dlugosc(); w3.wypisz();

    w3 = w1 + w2;

    w3.dlugosc(); w3.wypisz();

    getchar();

}
//--------------------------------------------------------

Pytanko jest następujące: Czy ten kod jest w miarę optymalnie napisany? Może dałoby się tutaj coś skrócić albo napisac inaczej? Jestem po prostu nowicjuszem w programowaniu obiektowym i nie mam "sznytu" jak to się mówi...

0

Inaczej bym zapisał poniższe deklaracje:

wektor operator+(const wektor&) const;   // optymalniej przez ref.
void wypisz() const;

Poza tym nie podoba mi się sposób wyliczania normy. Jeśli zapomnisz wywołać metodę norma(), to wektor wyświetli się niepoprawnie. Czyli albo trzymasz składową "norma", którą aktualizujesz przy każdej operacji na wektorze (chyba mało optymalne), albo nie trzymasz takiej składowej, a jedynie robisz metodę norma() wyliczającą normę na życzenie:

double wektor::norma() const
{
   return sqrt(x*x+y*y);
}

Wtedy w metodzie wypisz() wywołasz norma().

0

Możesz również wykorzystać operator konwersji
np:

operator float ();

operator float (){
  return sqrt(x*x+y*y);
}

i potem w obliczeniach wszelkiego rodzaju, z wykorzystaniem długości jego używać:

wector w;
float l=float(w)+double(w)+single(w); // ==3*float(w)

Dopoki nie oprogramujesz osobno double i inne typy (float = single, o ile mnie pamiec nie myli), dopóty wszystkie zmiennoprzecinkowe konwersje będą wykorzystywały ten sam operator.

0

Hmmm, nie tylko w obiektowym nowicjuszem :>

>g++ -W -Wall -Weffc++ -pedantic b.cpp
In file included from c:/lang/dev-cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../i
nclude/c++/3.4.2/backward/iostream.h:31,
                 from b.cpp:1:
c:/lang/dev-cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/backw
ard/backward_warning.h:32:2: warning: #warning This file includes at least one d
eprecated or antiquated header. Please consider using one of the 32 headers foun
d in section 17.4.1.2 of the C++ standard. Examples include substituting the <X>
 header for the <X.h> header for C++ includes, or <iostream> instead of the depr
ecated header <iostream.h>. To disable this warning use -Wno-deprecated.
b.cpp: In constructor `wektor::wektor()':
b.cpp:21: warning: `wektor::x' should be initialized in the member initializatio
n list
b.cpp:21: warning: `wektor::y' should be initialized in the member initializatio
n list
b.cpp:21: warning: `wektor::norma' should be initialized in the member initializ
ation list
b.cpp: In constructor `wektor::wektor(float, float)':
b.cpp:28: warning: `wektor::x' should be initialized in the member initializatio
n list
b.cpp:28: warning: `wektor::y' should be initialized in the member initializatio
n list
b.cpp:28: warning: `wektor::norma' should be initialized in the member initializ
ation list
b.cpp: At global scope:
b.cpp:57: error: `main' must return `int'
b.cpp:57: error: return type for `main' changed to `int'
</cpp>
Wystarczy?
Oczywiście to co Krolik napisał (przekazywanie do operatora+ przez ref).
No i bez sensu, że dlugosc() oblicza dlugosc, a nie zwraca; to tak jakbym nie mógł pobrać nagle długości wektora.
0
marcinEc napisał(a)

Hmmm, nie tylko w obiektowym nowicjuszem :>

g++ -W -Wall -Weffc++ -pedantic b.cpp
In file included from c:/lang/dev-cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../i
nclude/c++/3.4.2/backward/iostream.h:31,
from b.cpp
c:/lang/dev-cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/backw
ard/backward_warning.h2: warning: #warning This file includes at least one d
eprecated or antiquated header. Please consider using one of the 32 headers foun
d in section 17.4.1.2 of the C++ standard. Examples include substituting the <X>
header for the <X.h> header for C++ includes, or <iostream> instead of the depr
ecated header <iostream.h>. To disable this warning use -Wno-deprecated.
b.cpp: In constructor wektor::wektor()': b.cpp:21: warning: wektor::x' should be initialized in the member initializatio
n list
b.cpp warning: wektor::y' should be initialized in the member initializatio n list b.cpp:21: warning: wektor::norma' should be initialized in the member initializ
ation list
b.cpp: In constructor wektor::wektor(float, float)': b.cpp:28: warning: wektor::x' should be initialized in the member initializatio
n list
b.cpp warning: wektor::y' should be initialized in the member initializatio n list b.cpp:28: warning: wektor::norma' should be initialized in the member initializ
ation list
b.cpp: At global scope:
b.cpp error: main' must return int'
b.cpp error: return type for main' changed to int'
</cpp>
Wystarczy?
Oczywiście to co Krolik napisał (przekazywanie do operatora+ przez ref).
No i bez sensu, że dlugosc() oblicza dlugosc, a nie zwraca; to tak jakbym nie mógł pobrać nagle długości wektora.



OK. Uwzglednilem uwago Krolika i Dobrodzija. Tylko skąd Marciniec pod g++ wywaliło ci tyle błędów i uwag??? Ja ten program kompilowałem pod Builderem i nic nie zgłaszał takich rzeczy.
0
Lingus napisał(a)

OK. Uwzglednilem uwago Krolika i Dobrodzija. Tylko skąd Marciniec pod g++ wywaliło ci tyle błędów i uwag??? Ja ten program kompilowałem pod Builderem i nic nie zgłaszał takich rzeczy.

ano, czary.

Powłączane wszystkie ostrzeżenia i dodatkowo podpowiedzi Efficient C++ (-Weffc++), dodatkowo GCC trzyma się STANDARDU C++ (nagłówki C++ bez .h, int main(), a nie void main(), itp.).

0
marcinEc napisał(a)
Lingus napisał(a)

OK. Uwzglednilem uwago Krolika i Dobrodzija. Tylko skąd Marciniec pod g++ wywaliło ci tyle błędów i uwag??? Ja ten program kompilowałem pod Builderem i nic nie zgłaszał takich rzeczy.

ano, czary.

Powłączane wszystkie ostrzeżenia i dodatkowo podpowiedzi Efficient C++ (-Weffc++), dodatkowo GCC trzyma się STANDARDU C++ (nagłówki C++ bez .h, int main(), a nie void main(), itp.).

Aha. No ja programowałem do tej pory tylko pod Borlandem i nie znam gcc. A co to jest za kompilator i gdzie go mozna dostać ?

0
Lingus napisał(a)
marcinEc napisał(a)
Lingus napisał(a)

OK. Uwzglednilem uwago Krolika i Dobrodzija. Tylko skąd Marciniec pod g++ wywaliło ci tyle błędów i uwag??? Ja ten program kompilowałem pod Builderem i nic nie zgłaszał takich rzeczy.

ano, czary.

Powłączane wszystkie ostrzeżenia i dodatkowo podpowiedzi Efficient C++ (-Weffc++), dodatkowo GCC trzyma się STANDARDU C++ (nagłówki C++ bez .h, int main(), a nie void main(), itp.).

Aha. No ja programowałem do tej pory tylko pod Borlandem i nie znam gcc. A co to jest za kompilator i gdzie go mozna dostać ?

www.mingw.org i zaczynasz przygodę z GCC dla Windowsa :)

0

Spoko. Sciagnalem sobie Dev-C++ razem z MinGW i wszystko działa. Mam jeszcze takie pytanko: Sciagnalem takze kompilator GCJ do Javy. Nie wiecie moze jak go poprawnie skonfigurować pod Dev-C++ ???

0
marcinEc napisał(a)

dodatkowo GCC trzyma się STANDARDU C++ (nagłówki C++ bez .h, int main(), a nie void main(), itp.).

:/

gwoli wytlumaczenia: CBuilder Borlanda jest jednym z niewielu kompilatorow, ktory tak scisle trzyma sie standardow c++. a co do int main() i void main() to wedlug standardu oba zapisy sa poprawne. wyglada to tak:

int main() {
...
return 1;
}

lub

void main {
...
}

oba zapisy oznaczaja dokladnie to samo. przypadek drugi jest sygnalem dla kompilatora ze automatycznie ma utworzyc kod zwracania na koncu programu.

0

vixen: to bardzo ciekawe co piszesz, ale już dawno stwierdzono, że powtarzanie bzdur NIE powoduje, że stają się one prawdą...
Mówimy tu o C++ (czytaj ce-plus-plus).

http://www.comeaucomputing.com/techtalk/#voidmain [int main()]
http://www.comeaucomputing.com/techtalk/#mainexit [int main() {}]

// C
void main() {}

"TYLKO" warning:
a.c: In function main': a.c:2: warning: return type of 'main' is not int'

// C++
void main() {}

AŻ błąd:
aa.cpp error: main' must return int'

Ponieważ pewne osoby zaczęły się dziwnie do mnie odnosić, proszę oto dowód:

Standard C++ napisał(a)

3.6.1 Main function [basic.start.main]
1 A program shall contain a global function called main, which is the designated start of the program. It is
implementation-defined whether a program in a freestanding environment is required to define a main
function. [Note: in a freestanding environment, start-up and termination is implementation-defined; startup
contains the execution of constructors for objects of namespace scope with static storage duration; termination
contains the execution of destructors for objects with static storage duration. ]
2 An implementation shall not predefine the main function. This function shall not be overloaded. It shall
have a return type of type int, but otherwise its type is implementation-defined. All implementations
shall allow both of the following definitions of main:
int main() { /* ... / }
and
int main(int argc, char
argv[]) { /* ... */ }
In the latter form argc shall be the number of arguments passed to the program from the environment in
which the program is run. If argc is nonzero these arguments shall be supplied in argv[0] through
argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs)
(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the
name used to invoke the program or "". The value of argc shall be nonnegative. The value of
argv[argc] shall be 0. [Note: it is recommended that any further (optional) parameters be added after
argv. ]
[...]
A return statement in main has the effect of leaving the main function (destroying any objects with automatic
storage duration) and calling exit with the return value as the argument.
[int main() {} -> int main() { return 0;}]
If control reaches the end
of main without encountering a return statement, the effect is that of executing
return 0;

Nie ma słowa o standardowej void main()! Jeżeli jest inaczej (dodatkowe mainy) to jest tylko w konkretnej implementacji.

0

Co prawda nie znam się na tych różnych kompilatorach ale z tego co wiem standard C i standard C++ różnią się dużo od siebie różnymi szczegółami (oczywiście poza samym programowaniem obiektowym!). Poza tym MinGW dostarcza dwa kompilatory (poza tymi do innych jezyków programowania): gcc do plików w C oraz g++ do plików w C++ a borlandowy BCC32 v.5.5 obsługuje OBA standardy. Dodaktowo jest przeciewż masa innych kompilatorów C/C++:

  • kompilator Microsoft Visual C++ 7.1 dla systemu Windows
  • kompilator Intel C++ 7.1 dla systemów Windows i Linux
  • kompilator C++ Metrowerks CodeWarrior dla systemu Windows
  • kompilator C++ Sun Forte dla systemu Solaris (SPARC)

Może w tym gąszczu faktycznie ludziom się powaliły wszystkie standardy...

0

Standardy to jedno, a zycie to drugie. Fakt, ze standardy ulatwiaja na ogol zycie, ale nie ma sensu naginac swojego programu do trzymania sie scisle standardu C++, bo to wcale zwykle nie powoduje ze sie bedzie kompilowal na wiekszej liczbie kompilatorow. Tak samo rowniez, jesli g++ nie wywali zadnego warninga w trybie -Wall -pedantic itp. to nie oznacza, ze program jest napisany zgodnie ze standardem (zrodlo: man gcc), nie mowiac juz o tym, czy jest ladnie napisany. Po prostu nalezy sie kierowac zdrowym rozsadkiem i sprawdzac jak sie program kompiluje na roznych kompilatorach.

0

No pewnie masz rację Królik. ort! jest zbytnim konserwatystą w tej dziedzinie. ;)

A propos kompilatorów. Znalazłem na internecie taki trochę zapomniany kompilator Watcom w wersji Open Watcom 1.3. Zainstalowałem i stwierdzam, ze pomimo dosyć dużej toporności w obsłudze jego IDE jest niezły. Nie orientujecie się może jak spełnia on aktualne standardy C/C++ i jak się ma do produktów MS/Borland/GNU ???

// marcinEc do jasnej cholery! - Q

0
marcinEc napisał(a)

[int main() {} -> int main() { return 0;}]
If control reaches the end
of main without encountering a return statement, the effect is that of executing
return 0;

Nie ma słowa o standardowej void main()! Jeżeli jest inaczej (dodatkowe mainy) to jest tylko w konkretnej implementacji.</quote>

nie bede sie klocil

0
Lingus napisał(a)

No pewnie masz rację Królik. ort![Marciniec?! yep] jest zbytnim konserwatystą w tej dziedzinie. ;)
// marcinEc do jasnej cholery! - Q

</quote> Thnx Q :)

Konserwatystą? Nie, po prostu dzięki mnie się czegoś dowiesz... Ja też przy okazji :)
Hmm, dlaczego standard C++? Ano, bo rózne osoby mogą ten sam kod kompilować różnymi kompilatorami, nie bądźmy więc aż takimi egoistami :>

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