2011-12-05 15 views
25

Mam wektor jako element członkowski w klasie i chcę zwrócić odwołanie do niego za pomocą funkcji getVector(), aby móc go później zmodyfikować. Czy nie jest lepszą praktyką funkcja getVector(), która ma być stała? Jednak otrzymałem komunikat o błędzie "kwalifikatory odrzucone w powiązaniu referencji typu ..." w następującym kodzie. Co należy zmodyfikować?Odwołanie do zmiennej składowej wektorowej

class VectorHolder 
{ 
public: 
VectorHolder(const std::vector<int>&); 
std::vector<int>& getVector() const; 

private: 
std::vector<int> myVector; 

}; 

std::vector<int> &VectorHolder::getVector() const 
{ 
return myVector; 
} 

Odpowiedz

27

Ponieważ jest to funkcja składowa const, typem powrotu nie może być referencja bez stałych. Zrób to const:

const std::vector<int> &VectorHolder::getVector() const 
{ 
    return myVector; 
} 

Teraz jest w porządku.

Dlaczego jest w porządku? Ponieważ w funkcji składowej const każdy element staje się const w taki sposób, że nie można go zmodyfikować, co oznacza, że ​​myVector jest wektorem wektora , dlatego należy również zwrócić typ const, jeśli zwraca wartość reference.

Teraz nie można modyfikować obiektu sam obiekt. Zobacz, co można zrobić, a czego nie może:

std::vector<int> & a = x.getVector();  //error - at compile time! 

const std::vector<int> & a = x.getVector(); //ok 
a.push_back(10);       //error - at compile time! 

std::vector<int> a = x.getVector();  //ok 
a.push_back(10);       //ok 

Nawiasem mówiąc, zastanawiam się, dlaczego trzeba tak VectorHolder w pierwszej kolejności.

+0

W ten sposób jest więc niemożliwe, aby zmodyfikować wektor zwrócony później z kodu gdzie ją zamian? – arjacsoh

+0

@arjacsoh: To zależy. Zobacz edycję. – Nawaz

13

nie jest niczym niezwykłym, aby zadeklarować oba warianty const i zmienny, jak w przykładzie:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; 
} 
const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; 
} 

podstawowy problem z programem jest to, że wrócisz const odniesienia z metody const.

std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << error: return mutable reference from const method 
} 

więc zrobić to za pomocą tego formularza const:

const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

i kiedy jest to w nie sposób const lub klient posiada non-const odniesienia, można legalnie używać nie- metoda const:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; // << ok 
} 

wreszcie, można zwrócić wartość (w niektórych przypadkach):

std::vector<int> VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

ponieważ kopia nie wymaga mutacji i nie naraża na dane wewnętrzne.

, więc często będziesz deklarować oba warianty.

wyniki deklarując obie są:

VectorHolder m; 
const VectorHolder c; 

m.getVector().size(); // << ok 
c.getVector().size(); // << ok - no mutation 

m.getVector().push_back(a); // << ok 
c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned 

tak to wszystko działa dobrze (oprócz zwolnienia z metod).

2

Funkcja getVector może być zadeklarowana jako const. Zwraca referencję, którą można zmodyfikować, więc podczas gdy rzeczywista funkcja niczego nie modyfikuje w klasie, osoba wywołująca będzie mogła modyfikować dane wewnętrzne.

uznaniu jej jako:

std::vector<int>& getVector(); 

Jeśli chcesz funkcję powrotu wektor, który nie może być modyfikowana, w wykorzystaniu przez const modyfikujący zarówno wektora i funkcję:

const std::vector<int>& getVector() const; 
0

Powód jest taki, że funkcja składowa const powinna zwracać tylko odwołania do stałych. Dzieje się tak dlatego, że w funkcji stałej każdy element danych staje się stały.

Dlatego trzeba zadeklarować getVector() w ten sposób:

std::vector<int> &VectorHolder::getVector() const; 
+2

Niezależnie od powyższego, prawdopodobnie nie jest dobrym pomysłem na ujawnienie swojego wewnętrznego pojemnika. Jeśli pewnego dnia zdecydujesz się na migrację z wektora do mapy, wpłynie to na twoich użytkowników. Proponuję zamiast tego implementować iteratory. – Lev

Powiązane problemy