2012-04-28 15 views
5

Powiedzmy mamy tej klasie:Jak używać łańcucha przeciążenia operatora bez modyfikowania argumentów?

class A 
{ 
public: 
    int a; 

    A(int b) 
    { 
     a = b; 
    } 
}; 

Chciałbym stworzyć A + przeciążenie taki sposób, że można go używać jak to

A a(1),b(2),c(3),&d; 
d = a + b + c; 

bez modyfikowania zawartości każdego obiektu. Kolejnym logicznym byłoby przydzielenie nowego fragment pamięci za każdym razem tak:

A &operator+ (const A &b) 
{ 
    A *c = new A(a+b.a); 
    return *c; 
} 

Ale to byłoby utworzyć nowy problem: wyniki pośrednie są tracone, powodując wycieki pamięci. Mogłem łatwo rozwiązać ten problem, wykonując funkcję statyczną, która pobiera trzy referencje obiektu i przechowuje sumę pierwszych dwóch w trzecim, ale jestem gotów założyć się, że musi istnieć jakiś sposób, aby uczynić + przeciążenie sposób, w jaki chcę.

Pytanie brzmi: czy istnieje jakikolwiek sposób, w jaki mogę użyć łańcucha przeciążenia operatora, który nie modyfikuje operandów bez powodowania wycieków pamięci?

Odpowiedz

9

można po prostu użyć podanie o wartości i zrobić to:

A operator+ (A other) //pass by value 
{ 
    other.a += a; 
    return other; 
} 

Albo, ponieważ człon a jest publicznie dostępny, można (a powinny) sprawiają operator+ funkcję niebędącego państwem członkowskim :

A operator+(A left, A const &right) 
{ 
    left.a += right.a; 
    return left; 
} 

Zauważ, że pierwszy argument jest akceptowana wartością, a drugi przez odniesienie. W ten sposób nie musisz zadeklarować zmiennej lokalnej w funkcji. Możesz użyć pierwszego parametru; wszak jest on lokalny dla funkcji, możesz zrobić cokolwiek chcesz z nią zrobić: w tym przypadku dodajemy do niego tylko right.a i zwracamy.


Lepszy projekt klasie byłoby to: (czytaj komentarze)

class A 
{ 
    int a; //make it private 
public:  
    A(int b) : a(b) //use member initialization list 
    { 
    } 
    A& operator+=(A const & other) //add `+=` overload, as member of the class 
    { 
     a += other.a; 
     return *this; 
    } 
}; 

//and make `+` non-member and non-friend 
A operator+(A left, A const & right) 
{ 
    left += right; //compute this in terms of `+=` which is a member function 
    return left; 
} 
+1

+1 za unikanie ręcznego kopiowania. – Sven

+0

Przepraszam, ale twoja odpowiedź zdaje się ignorować fakt, że konkretnie pytałem o sposób, aby nie modyfikować żadnego z obiektów operandowych –

+0

@ user803253: Nie modyfikuję * operandów *; operandy są przekazywane jako wartość, co oznacza, że ​​modyfikowane w funkcji są * kopie * operandów. W każdym razie, napisałem lepszy projekt, który powinieneś przyjąć. – Nawaz

4

Nie ma potrzeby używania wskaźników wewnątrz operator+. Można przeznaczyć pośredni obiektu w stosie, a następnie powrócić go:

A operator+ (const A &b) 
{ 
    A c(a+b.a); 
    return c; 
} 

lub po prostu:

A operator+ (const A &b) 
{ 
    return A(a+b.a); 
} 

Albo jeszcze prościej:

A operator+ (const A &b) 
{ 
    return a+b.a; 
} 

Ponieważ domyślnie nazywa A::A(int).

Należy pamiętać, że usunąłem odniesienie z typu zwracanego. Nie można zwrócić odniesienia nielokalnego do lokalnego.

Wtedy go używać w ten sposób:

A a(1),b(2),c(3),d; 
d = a + b + c; 

Zauważ, że d ma już odniesienia.

+0

Alert: Wracasz odniesień do tymczasowych. To nie jest dobry pomysł! –

+0

działa świetnie! dzięki. Wiedziałem, że coś prostego trzeba zrobić. –

+0

Gdy tylko opublikowałem odpowiedź, zauważyłem, że OP odsyła, ale od razu poprawiłem odpowiedź. – mfontanini

Powiązane problemy