c++ friend function – supraîncărcare operator istream >> (Programare, C++, Supraîncărcarea Operatorului, Prieten, Operator Keyword)

user399415 a intrebat.
a intrebat.

Întrebarea mea este în ceea ce privește funcțiile friend, precum și supraîncărcarea << și >>. Din câte am înțeles, credeam că funcțiile friend pot (și ar trebui) să acceseze direct variabilele membre private. Cu toate acestea, în cazul pe care îl am aici, compilatorul ar accepta fișierul meu .cxx numai atunci când am folosit funcții „get” pentru a obține fiecare variabilă privată.

Iată fișierul meu de antet

class BigNum 
public:

// CONSTRUCTORS and DESTRUCTORS
    BigNum();                            
    BigNum(int num, size_t optional_base = 10);                         
    BigNum(const char strin[], size_t optional_base = 10);

// MEMBER FUNCTIONS
    size_t get_digit(size_t index) const;
    size_t get_used() const;
    size_t get_capacity() const;
    size_t get_base() const;
    bool get_sign() const;

// FRIEND FUNCTIONS
    friend std::ostream& operator<<(std::ostream &os, const BigNum &bignum);
    friend std::istream& operator>>(std::istream &is, BigNum &bignum);

private:
    size_t base;            
    size_t *digits;          
    bool positive;          
    size_t used;              

Iată fișierul .cxx corespunzător cu implementările pentru funcțiile prietene

#include "file.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>

using namespace std;

std::ostream& operator <<(std::ostream &os, const BigNum &bignum)
{
if (bignum.get_sign() == false)
    os << '-';

for (size_t i = 0; i < bignum.get_used(); ++i)
    os << bignum.get_digit(bignum.get_used() - i - 1);

return os;
}

std::istream& operator >>(std::istream &is, BigNum &bignum)
{
for (size_t i = 0; i < bignum.get_used(); ++i)
    is >> bignum.digits[i];

return is;
}

Deci, în această privință, operatorii prieteni de mai sus au fost compilați corect. Cu toate acestea, de ce se întâmplă că operatorul meu >> poate accesa direct o variabilă privată (este >> bignum.digits[i]), dar restul variabilelor private trebuie să fie recuperate prin funcții „get

Mai jos, când încerc să scriu operatorii de supraîncărcare în acest sens (cum am crezut că funcțiile prietene ar trebui să apeleze corect variabilele private):

std::ostream& operator <<(std::ostream &os, const BigNum &bignum)
{
if (bignum.positive == false)
    os << '-';

for (size_t i = 0; i < bignum.used; ++i)
    os << bignum.digits[used - i - 1];

return os;
}

std::istream& operator >>(std::istream &is, BigNum &bignum)
{
for (size_t i = 0; i < bignum.used); ++i)
    is >> bignum.digits[i];

return is;
}

Obțin următoarele erori.

BigNum2.cxx: In function `std::ostream&
   csci2270_hw1B::operator<<(std::ostream&, const csci2270_hw1B::BigNum&)':
BigNum2.cxx:201: error: `used' undeclared (first use this function)
BigNum2.cxx:201: error: (Each undeclared identifier is reported only once for
   each function it appears in.)
BigNum2.cxx: In function `std::istream&
   csci2270_hw1B::operator>>(std::istream&, csci2270_hw1B::BigNum&)':
BigNum2.cxx:208: error: syntax error before `)' token

Compilatorul pe care îl folosesc este g++ (versiunea 3.3.1). Orice ajutor este apreciat, vă mulțumesc.

Revizuit:

Am actualizat codul astfel încât obiectul bignum să poată accesa variabilele private. Am făcut următoarele la supraîncărcarea operatorului friend << și s-a compilat bine. Mulțumesc pentru comentarii, asta a fost o greșeală de începător.

std::ostream& operator <<(std::ostream &os, const BigNum &bignum)
{
if (bignum.positive == false)
    os << '-';

for (size_t i = 0; i < bignum.used; ++i)
    os << bignum.digits[bignum.used - i - 1];

return os;
}

Cu toate acestea, compilatorul produce în continuare erori pentru operatorul >>.

BigNum2.cxx: În funcția std::istream&
csci2270_hw1B::operator>>(std::istream&, csci2270_hw1B::BigNum&)':
BigNum2.cxx:208: error: syntax error before
)’ token

>> ar trebui să citească un număr, iar variabila membră privată „used” ar trebui să înregistreze lungimea matricei. Sunt încă oarecum confuz cu privire la motivul pentru care compilatorul acceptă

std::istream& operator >>(std::istream &is, BigNum &bignum)
{
for (size_t i = 0; i < bignum.get_used()); ++i)
    is >> bignum.digits[i];

return is;
}

în loc de:

std::istream& operator >>(std::istream &is, BigNum &bignum)
{
for (size_t i = 0; i < bignum.used); ++i)
    is >> bignum.digits[i];

return is;
}

Vreo idee? mulțumesc.

3 răspunsuri
Jerry Coffin

O funcție prietenă are acces la datele private ale clasei, dar nu are nu obține un this pointer pentru a face acest lucru automat, astfel încât fiecare acces la datele clasei (private sau nu) trebuie să fie calificat. De exemplu, aceasta:

os << bignum.digits[used - i - 1];

trebuie să fie:

os << bignum.digits[bignum.used - i - 1];

In silico

Nu ați calificat used în prima funcție – trebuie să fie bignum.used. Supraîncărcările operatorului sunt definite la nivel global, deci nu primesc un this pointer. Cu toate acestea, funcțiile prietene au acces la membrii privați ai clasei.

std::ostream& operator <<(std::ostream &os, const BigNum &bignum) 
{ 
    if (bignum.positive == false) 
        os << '-'; 

    for (size_t i = 0; i < bignum.used; ++i) 
        // Note "bignum.used", instead of "used".
        os << bignum.digits[bignum.used - i - 1];     
    return os; 
} 

std::istream& operator >>(std::istream &is, BigNum &bignum) 
{ 
    for (size_t i = 0; i < bignum.used; ++i) 
        is >> bignum.digits[i]; 

    return is; 
} 

Priyankar Ghosh

Se pare că există un ‘)’ în plus în următoarea linie imediat după bignum.used.

 for (size_t i = 0; i < bignum.used**)**; ++i)