/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
Bech_bb 500
kyllekylle 500
jdjespers.. 500
gibson 300
scootergr.. 300
molokyle 287
10  strarup 270
overloading af < i c++
Fra : Michael Birkmose


Dato : 08-05-03 16:33

Hejsa,

Jeg har lavet to objekter:

Vertex *v1 = new Vertex();
Vertex *v2 = new Vertex();

nu vil jeg gerne kunne gøre noget ala:
if (v1 < v2)
(...)


Jeg har prøvet nedenstående løsninger uden held (de bliver ikke kaldt
når jeg kører min v1 < v2 kode.


bool Vertex:erator< (Vertex param) {
(..)
}

bool Vertex:erator< (Vertex *param) {
(..)
}


Jeg tror problemet er fordi jeg sammenlinger to pointer til objekter, og
ikke to objekter.
Men jeg har brug for at kunne sammenlinge de to.

Er det muligt?


 
 
Robert Larsen (08-05-2003)
Kommentar
Fra : Robert Larsen


Dato : 08-05-03 16:43

Michael Birkmose wrote:

> Jeg tror problemet er fordi jeg sammenlinger to pointer til objekter, og
> ikke to objekter.
> Men jeg har brug for at kunne sammenlinge de to.
>
> Er det muligt?
>

if((*v1) < (*v2))
{
...
}


Robert


Kent Friis (08-05-2003)
Kommentar
Fra : Kent Friis


Dato : 08-05-03 17:14

Den Thu, 08 May 2003 17:32:52 +0200 skrev Michael Birkmose:
>Hejsa,
>
>Jeg har lavet to objekter:
>
>Vertex *v1 = new Vertex();
>Vertex *v2 = new Vertex();
>
>nu vil jeg gerne kunne gøre noget ala:
>if (v1 < v2)
> (...)
>
>
>Jeg har prøvet nedenstående løsninger uden held (de bliver ikke kaldt
>når jeg kører min v1 < v2 kode.
>
>
>bool Vertex:erator< (Vertex param) {
> (..)
>}
>
>bool Vertex:erator< (Vertex *param) {
> (..)
>}
>
>Jeg tror problemet er fordi jeg sammenlinger to pointer til objekter, og
>ikke to objekter.
>Men jeg har brug for at kunne sammenlinge de to.
>
>Er det muligt?

Hvorfor bruger du pointere?

Vertex v1;
Vertex v2;

Umiddelbart ligner din kode java-kode, java-folk er enormt glade for
pointere (de kalder dem bare noget andet), og fordi at man bruger
pointere så tit i java, slipper man for at skulle skrive *v1 hver
gang man skal bruge det objekt pointeren peger på. I C++ er det
sjældent nødvendigt at bruge pointere.

Mvh
Kent
--
.~. .~.
/V\ From Palm Pilot to S/390 /V\
// \\ Truly scalable operating system // \\
/( )\ Linux /( )\
^^-^^ ^^-^^

na na (08-05-2003)
Kommentar
Fra : na na


Dato : 08-05-03 17:56


"Kent Friis" <leeloo@phreaker.net> wrote in message
news:b9dvnb$fhh$2@sunsite.dk...
> Hvorfor bruger du pointere?

> Umiddelbart ligner din kode java-kode, java-folk er enormt glade for
> pointere (de kalder dem bare noget andet), og fordi at man bruger
> pointere så tit i java, slipper man for at skulle skrive *v1 hver
> gang man skal bruge det objekt pointeren peger på. I C++ er det
> sjældent nødvendigt at bruge pointere.

Undskyld hvis jeg lige skifter emne engang, men jeg er nu alligevel lige
nødt til at blande mig

Say what?

Den udtalelse kunne jeg nu altså godt tænke mig lidt nærmere argumentation
for... Altså den der med at der sjældent er brug for pointere i C++ :p



Lad os tage et super simpelt eksempel...

Du skal indlæse en tilfældig tekstfil, der indeholder et ukendt antal
linjer, og længden på disse linjer kender du heller ikke.
Når hele filen er blevet indlæst, lukker du filen, og udskriver de X linjer

Hvordan vil du helt præcist bære dig ad med det uden at bruge pointere...



Noget helt andet er at ham der skrev det oprindelige indlæg bruger
Vertex-objekter, så jeg kunne mistænke at han leger med noget 3D grafik,
måske ligefrem en 3D engine.
Hvis ikke det han laver er super simpelt (måske ligefrem primitivt) kan han
da ikke, før programkørsel, være sikker på hvor mange vertices han får brug
for, og så kommer pointerne på banen igen...



Jeg kunne nok blive ved i et godt stykke tid endnu, og komme på eksempler
hvor der skal bruges pointere.



Nej... Nu skal du ikke komme med en eller anden forklaring på at man da bare
bruger f.eks. en vector-container i stedet for, og index'erer ind i dette, i
stedet for at bruge pointere... Ehh... Gad vide om ikke vector'en internt
benytter sig af pointere ;) *hint hint*



OK... Jeg kommer lige ned på jorden igen (Ikke ophidset men kunne måske godt
lyde sådan)... Kan du ikke lige komme med et enkelt, eksempel på et brugbart
dagligdags-program, hvor der ikke er brug for pointere.



Min pointe er: Efter min mening, er pointere en så central del af C og C++,
at man ikke kan undgå at bruge det tit... Jeg har efterhånden haft gang i en
del forskellige projekter (lige fra de helt små, til de helt store), og jeg
tror ikke der er ét hvor jeg ikke har haft brug for pointere



Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 18:53


"na na" <na@na.na> wrote

[8<8<8<]
> Du skal indlæse en tilfældig tekstfil, der indeholder et ukendt antal
> linjer, og længden på disse linjer kender du heller ikke.
> Når hele filen er blevet indlæst, lukker du filen, og udskriver de X
linjer
>
> Hvordan vil du helt præcist bære dig ad med det uden at bruge pointere...

Helt præcist :
<code>
#include <fstream>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <iterator>
#include <exception>

int main(int argc, char* argv[])
{
using namespace std;

try {

for(int i = 1; argc != i; ++i) {
ifstream file(argv[i]);
if(!file) {
cerr << "unable to open file: \"" << argv[i] << "\"";
continue;
}

// calculate the file size
file.seekg(0, ios::end);
const size_t file_size = file.tellg();
file.seekg(0, ios::beg);

// allocate the memory for the file content
vector<char> file_content(file_size+1);

// read the entire file into the buffer
file.read(&file_content[0], file_size);
file_content[file_size] = '\0';

// print the entire file
copy(file_content.begin(), file_content.end(),
ostream_iterator<char, char>(cout));
cout << endl;
}
}
catch(const exception& x) {
cerr << x.what() << endl;
return EXIT_FAILURE;
}
catch(...) {
cerr << "unexpected C++ exception detected" << endl;
return EXIT_FAILURE;
}
}
</code>

og hvis du gerne vil have det linie orienteret:
<code>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <iterator>
#include <exception>

int main(int argc, char* argv[])
{
using namespace std;

try {

for(int i = 1; argc != i; ++i) {
ifstream file(argv[i]);
if(!file) {
cerr << "unable to open file: \"" << argv[i] << "\"";
continue;
}

vector<string> lines;
string line;
while(getline(file, line)) {
lines.push_back(line);
}

// print the entire file
copy(lines.begin(), lines.end(),
ostream_iterator<string, char>(cout, "\n"));
cout << endl;
}
}
catch(const exception& x) {
cerr << x.what() << endl;
return EXIT_FAILURE;
}
catch(...) {
cerr << "unexpected C++ exception detected" << endl;
return EXIT_FAILURE;
}
}
</code>

Du specificerer hvilke filer, der skal åbnes som kommandolinie parametre.
Programmerne er komplete med fejl håndtering etc.

Bemærk iøvrigt at programmer var nemme at skrive.

[8<8<8<]
> Hvis ikke det han laver er super simpelt (måske ligefrem primitivt) kan
han
> da ikke, før programkørsel, være sikker på hvor mange vertices han får
brug
> for, og så kommer pointerne på banen igen...

Brug
vector<Vertex>

>
>
>
> Jeg kunne nok blive ved i et godt stykke tid endnu, og komme på eksempler
> hvor der skal bruges pointere.

Kan bruges pointere.

[8<8<8<]
> Nej... Nu skal du ikke komme med en eller anden forklaring på at man da
bare
> bruger f.eks. en vector-container i stedet for, og index'erer ind i dette,
i
> stedet for at bruge pointere... Ehh... Gad vide om ikke vector'en internt
> benytter sig af pointere ;) *hint hint*

Det væsentlige er ikke hvordan et bibliotek er skrevet.
Det væsentlige er hvordan man skriver sin applikationskode.

[8<8<8<]
> OK... Jeg kommer lige ned på jorden igen (Ikke ophidset men kunne måske
godt
> lyde sådan)... Kan du ikke lige komme med et enkelt, eksempel på et
brugbart
> dagligdags-program, hvor der ikke er brug for pointere.

Her er et eksempel, hvor der stor set ikke bruges pointeresom jeg brugte i
en nyhedsgruppe forleden.
Nedenstående program får som kommandolinie option angivet navnet på nogle
filer, hvori der står en række regne-udtryk, som f.eks
1*2+3*4
adskilt med mellemrum.
Programmet parser udtrykket og beregner resultatet

Programmet processerer i høj grad tekst og skal kunne håndtere dynamisk
input.
Eneste begrænsning er mængden af tilgængelig hukommelse.

Programmet er skrevet i 100 % Standard C++ (med anvendelse af Spirit parser
biblioteket - http://www.boost.org/libs/spirit/index.html), og vil derfor
kunne oversætte på alle platforme hvor der findes en Standard C++ compiler.

Bemærk at syntaxen er beskrevet på en form, der minder meget om EBNF.

Det er ikke et program der arbejder sprogmæssigt på et lavt niveau i
forbindelse med tekst processering.
Det er ikke et program der laver fuldstændigt trivielle opgaver.
Det er ikke et urealistisk program.
Det er ikke et program der anvender teknikker der skalerer dårligt
(performance mæssigt, vedligeholdelses mæssigt etc.).
Programmet er komplet med fejlhåndtering.
Programmet indholder ikke nogen explicit dynamisk hukommelse håndtering
eller pointer aritmetik i forbindelse med parsningen.
Det er ikke et program der er udviklet med lav programmør produktivitet.
Der er ingen risiko for problemer som memory-leak, dangling pointer, buffer
overrun etc.

<83 linier Standard C++ kode>
#include <iostream>
#include <fstream>
#include <stack>
#include <functional>
#include "boost/spirit/spirit.hpp"

using namespace std;
using namespace spirit;

stack<int> evaluation_stack;

struct do_push_int
{
typedef int arg_type;
void operator()(int n) const
{ evaluation_stack.push(n); }
};

template <class operation>
struct do_operation
{
void operator()(char const* /*begin*/, char const* /*end*/) const
{
const int rhs = evaluation_stack.top();
evaluation_stack.pop();
const int lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(operation()(lhs, rhs));
}
};

struct do_negate
{
void operator()(char const* /*begin*/, char const* /*end*/) const
{
const int lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(-lhs);
}
};

int main(int argc, char* argv[])
{
rule<> expression, term, factor, integer;
integer =
int_p[do_push_int()];
factor =
integer
| '(' >> expression >> ')'
| ('-' >> factor)[do_negate()];
term =
factor >>
* ( ('*' >> factor)[do_operation<multiplies<int> >()]
| ('/' >> factor)[do_operation<divides <int> >()]
);
expression =
term >>
*( ('+' >> term)[do_operation<plus <int> >()]
| ('-' >> term)[do_operation<minus<int> >()]
);

// Process each file specified on the command line
for(int i = 1; i != argc; ++i) {
ifstream file(argv[i]); // uses char pointer and pointer arithmetic
if(file) {
// Process each line in the file
string text;
while(file >> text) {
if(parse(text.c_str(), expression, space).full) {
cout << "Result: " << text << " = " << evaluation_stack.top()
<< endl;
evaluation_stack.pop();
}
else {
cerr << "Error: \"" << text << "\" is not a valid expression"
<< endl;
// flush the evaluation stack
evaluation_stack = stack<int>();
}
}
}
else {
cerr << "Error: Unable to open file: " << argv[i] << endl;
}
}
}
<83 linier Standard C++ kode/>

[8<8<8<]
> Min pointe er: Efter min mening, er pointere en så central del af C og
C++,

ja

> at man ikke kan undgå at bruge det tit...

Oftere end mange tror

> Jeg har efterhånden haft gang i en
> del forskellige projekter (lige fra de helt små, til de helt store), og
jeg
> tror ikke der er ét hvor jeg ikke har haft brug for pointere

Naturligvis.

Når man skrive
<code>
int main(int argc, char* argv[])
{
// ...
}
</code>

bruger man pointere.


Venlig hilsen

Mogens Hansen



Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 18:55


"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:b9e564$pvu$1@news.cybercity.dk...

[8<8<8<]
> // allocate the memory for the file content
> vector<char> file_content(file_size+1);

Nul terminering bruges faktisk ikke i dette eksempel, så
vector<char> file_content(file_size);

[8<8<8<]
> file_content[file_size] = '\0';

Dette er også overflødigt.

Venlig hilsen

Mogens Hansen



Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 19:03


"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:b9e564$pvu$1@news.cybercity.dk...

[8<8<8<]
> // calculate the file size
> file.seekg(0, ios::end);
> const size_t file_size = file.tellg();
> file.seekg(0, ios::beg);
>
> // allocate the memory for the file content
> vector<char> file_content(file_size+1);
>
> // read the entire file into the buffer
> file.read(&file_content[0], file_size);
> file_content[file_size] = '\0';

Hele indlæsningen stammer fra noget andet kode, hvor der var optimeret noget
for performance, og hvor filindholdet skulle sendes til en funktion, der
kræver en 0 termineret text.

Ellers kan indlæsningen klares med
<code>
vector<char> file_content;
char c;
while(file >> c) {
file_content.push_back(c);
}
</code>

og så ligner mere det eksempel, hvor filen læses ind linie for linie.

Venlig hilsen

Mogens Hansen



na na (08-05-2003)
Kommentar
Fra : na na


Dato : 08-05-03 19:00


"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:b9e564$pvu$1@news.cybercity.dk...

<snip: en masse kode-eksempler>

Ja OK... Point taken :)
Jeg overgiver mig... Med STL bliver det faktisk ikke kun nemmere at undgå
pointere (og derved mem-leaks, dangling pointers, etc), det bliver ligefrem
betydeligt meget pænere at se på.

Jeg har godt nok aldrig rigtig været den helt store tilhænger at STL, men
efter den her opsang kan jeg da godt se at det er på tide at komme igang.

Just the wakeupcall I needed ;D



Christian Larsen (08-05-2003)
Kommentar
Fra : Christian Larsen


Dato : 08-05-03 19:07

"Mogens Hansen" <mogens_h@dk-online.dk> wrote in
news:b9e564$pvu$1@news.cybercity.dk:

> // read the entire file into the buffer
> file.read(&file_content[0], file_size);

Ikke for at blande mig, men når du skriver &file_content[0] får du jo en
pointer til det første element i file_content. Så helt uden pointerer er
det vel ikke?

--

Remove "nospam" from the e-mail address.

Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 19:15


"Christian Larsen" <christianlarsen@nospam.get2net.dk> wrote in message
news:Xns9375CC9DE589christianlarsen@62.243.74.162...

> Ikke for at blande mig, men når du skriver &file_content[0] får du jo en
> pointer til det første element i file_content. Så helt uden pointerer er
> det vel ikke?

Nej, men så tager du bare en af de andre bud på indlæsningen af filen
Måden at få navnet på filen, der skal læses er heller ikke uden pointere og
pointer arithmetik.

Venlig hilsen

Mogens Hansen



Byrial Jensen (08-05-2003)
Kommentar
Fra : Byrial Jensen


Dato : 08-05-03 20:21

Mogens Hansen wrote:

> int main(int argc, char* argv[])
> {
> using namespace std;
>
> try {
>
> for(int i = 1; argc != i; ++i) {

Garanterer C++-standarden at argc er større end 0?

I C er det kun garanteret at argc ikke er negativ, men værdien kan godt
være 0 - hvilket ville få ovenstående kode til at fejle.


Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 20:43


"Byrial Jensen" <bjensen@nospam.dk> wrote

[8<8<8<]
> I C er det kun garanteret at argc ikke er negativ, men værdien kan godt
> være 0 - hvilket ville få ovenstående kode til at fejle.

Tak, du har ret. Det er det samme i C++.
Men hvis "argc != 0" angiver "argv[0]" det der blev brug til at starte
programmet eller en tom streng.

Venlig hilsen

Mogens Hansen



Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 21:53


"Byrial Jensen" <bjensen@nospam.dk> wrote

[8<8<8<]
> I C er det kun garanteret at argc ikke er negativ, men værdien kan godt
> være 0 - hvilket ville få ovenstående kode til at fejle.

Jeg er tilhænger af en offensiv kodestil, hvor fejl i programmet er så store
at man kun vanskeligt kan undgå at opdage det.
Derfor skriver jeg rutinemæssigt
for(int i = 1; argc != i; ++i) {
i stedet for
for(int i = 1; argc > i; ++i) {

Den fejl du rigtigt påpeger vil formodentlig vise sig tydeligt.

På en maskine med MMU vil fejlen næsten med sikkerhed give en hardware trap,
hvis "argc == 0".
På en almindelig IA32 baseret maskine, vil programmet prøve køre hele
adresserummet igennem indtil hardwaren stopper det.
Selv hvis hardwaren ikke stopper programmet, så vil alene det at tælle "i"
op indtil den wrapper rundt vil tage af størrelses ordenen sekunder, og
programmet vil udskrive en masse sludder.

Venlig hilsen

Mogens Hansen



Mogens Hansen (08-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 08-05-03 17:26


"Michael Birkmose" <birkmose@cs.auc.dk> wrote

[8<8<8<]
> bool Vertex:erator< (Vertex param) {

Er der nogen speciel grund til at du overfører "param" by-value ?
(Formodentlig ikke)
Skriv i stedet:

bool Vertex:erator<(const Vertex& param) const
{
// ...
}

[8<8<8<]
> bool Vertex:erator< (Vertex *param) {

drop denne version.


Venlig hilsen

Mogens Hansen



Michael Birkmose (08-05-2003)
Kommentar
Fra : Michael Birkmose


Dato : 08-05-03 17:50

Hvad betyder alle de const'er?

Mogens Hansen wrote:
> "Michael Birkmose" <birkmose@cs.auc.dk> wrote
>
> [8<8<8<]
>
>>bool Vertex:erator< (Vertex param) {
>
>
> Er der nogen speciel grund til at du overfører "param" by-value ?
> (Formodentlig ikke)
> Skriv i stedet:
>
> bool Vertex:erator<(const Vertex& param) const
> {
> // ...
> }
>
> [8<8<8<]
>
>>bool Vertex:erator< (Vertex *param) {
>
>
> drop denne version.
>
>
> Venlig hilsen
>
> Mogens Hansen
>
>


na na (08-05-2003)
Kommentar
Fra : na na


Dato : 08-05-03 18:02


"Michael Birkmose" <birkmose@cs.auc.dk> wrote in message
news:b9e1rn$1kf$1@sunsite.dk...
> Hvad betyder alle de const'er?

> > bool Vertex:erator<(const Vertex& param) const

const Vertex& param
----------------------
Param er en reference til et 'kontant' Vertex-objekt.
Funktionen ændrer altså ikke værdien af param.



Det sidste const:
----------------
Eks:
vtxA < vtxB
vtxA.operator<(vtxB)
----------------------
operator< - funktionen ændrer ikke værdien af det objekt som kalder
funktionen.
Altså vtxA (ovenstående to eksempler) ændrer ikke værdi (Dvs. variablerne i
klassen ændrer ikke værdi)



Per Abrahamsen (09-05-2003)
Kommentar
Fra : Per Abrahamsen


Dato : 09-05-03 17:47

Michael Birkmose <birkmose@cs.auc.dk> writes:

> Hejsa,
>
> Jeg har lavet to objekter:
>
> Vertex *v1 = new Vertex();
> Vertex *v2 = new Vertex();
>
> nu vil jeg gerne kunne gøre noget ala:
> if (v1 < v2)
> (...)

Har du prøvet

bool operator< (const Vertex *a, const Vertex *b)
{ ... }

?

Jeg aner ikke det virker, og vil ikke anbefale det hvis det gør, da
operator< allerede er defineret for pointere, og du risikerer at en
eller anden tredjeparts-funktion afhænger af den standard definition.

Så jeg vil tilslutte mig de mange der anbefaler at du vænner dig til
at bruge værdier (eller til nød referencer) i stedet for pointere.

Vertex v1; // value
Vertex& v2 = *new Vertex(); // reference

if (v1 < v2 && v2 < v1)
cout << strange order;

bool Vertex:erator< (const Vertex& other) const
{ ... }


Jeg har tilladt mig at tilføje nogen "const" da jeg meget stærkt vil
anbefale at "<" ikke ændrer på sine argumenter.

Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408193
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste