Sök…
Introduktion
Väl utformade klasser kapslar in deras funktionalitet, döljer implementeringen samtidigt som de ger ett rent, dokumenterat gränssnitt. Detta tillåter ny design eller ändring så länge gränssnittet är oförändrat.
I ett mer komplext scenario kan flera klasser som förlitar sig på varandras implementeringsinformation krävas. Vänklasser och funktioner ger dessa kamrater tillgång till varandras detaljer utan att kompromissa med inkapslingen och informationen som döljer det dokumenterade gränssnittet.
Vänfunktion
En klass eller en struktur kan förklara vilken funktion den är som vän. Om en funktion är en klassvän kan den komma åt alla den skyddade och privata medlemmarna:
// Forward declaration of functions.
void friend_function();
void non_friend_function();
class PrivateHolder {
public:
PrivateHolder(int val) : private_value(val) {}
private:
int private_value;
// Declare one of the function as a friend.
friend void friend_function();
};
void non_friend_function() {
PrivateHolder ph(10);
// Compilation error: private_value is private.
std::cout << ph.private_value << std::endl;
}
void friend_function() {
// OK: friends may access private values.
PrivateHolder ph(10);
std::cout << ph.private_value << std::endl;
}
Tillgångsmodifierare ändrar inte vänssemantik. Offentliga, skyddade och privata förklaringar från en vän är likvärdiga.
Vändeklarationer ärvs inte. Om vi till exempel underklassar PrivateHolder
:
class PrivateHolderDerived : public PrivateHolder {
public:
PrivateHolderDerived(int val) : PrivateHolder(val) {}
private:
int derived_private_value = 0;
};
och försöka komma åt dess medlemmar, vi får följande:
void friend_function() {
PrivateHolderDerived pd(20);
// OK.
std::cout << pd.private_value << std::endl;
// Compilation error: derived_private_value is private.
std::cout << pd.derived_private_value << std::endl;
}
Observera att PrivateHolderDerived
medlemsfunktionen inte kan komma åt PrivateHolder::private_value
, medan PrivateHolder::private_value
kan göra det.
Vänmetod
Metoder kan deklareras som vänner och funktioner:
class Accesser {
public:
void private_accesser();
};
class PrivateHolder {
public:
PrivateHolder(int val) : private_value(val) {}
friend void Accesser::private_accesser();
private:
int private_value;
};
void Accesser::private_accesser() {
PrivateHolder ph(10);
// OK: this method is declares as friend.
std::cout << ph.private_value << std::endl;
}
Vänsklassen
En hel klass kan förklaras som vän. Vänklassdeklaration betyder att alla medlemmar i vännen kan få åtkomst till privata och skyddade medlemmar i den deklarerande klassen:
class Accesser {
public:
void private_accesser1();
void private_accesser2();
};
class PrivateHolder {
public:
PrivateHolder(int val) : private_value(val) {}
friend class Accesser;
private:
int private_value;
};
void Accesser::private_accesser1() {
PrivateHolder ph(10);
// OK.
std::cout << ph.private_value << std::endl;
}
void Accesser::private_accesser2() {
PrivateHolder ph(10);
// OK.
std::cout << ph.private_value + 1 << std::endl;
}
Vänklassdeklarationen är inte reflexiv. Om klasser behöver privat åtkomst i båda riktningarna, behöver de båda vändeklarationer.
class Accesser {
public:
void private_accesser1();
void private_accesser2();
private:
int private_value = 0;
};
class PrivateHolder {
public:
PrivateHolder(int val) : private_value(val) {}
// Accesser is a friend of PrivateHolder
friend class Accesser;
void reverse_accesse() {
// but PrivateHolder cannot access Accesser's members.
Accesser a;
std::cout << a.private_value;
}
private:
int private_value;
};