Static Members and Friends
Table of Contents
Static Data Members
-
Single Instance: A static data member is allocated only once in memory, regardless of how many objects of that class are created.
-
Initialization: Must be defined and initialized outside the class definition to allocate storage.
-
Access:
- Through the class name:
ClassName::staticMember
. - Through an instance (not recommended, but allowed):
objectName.staticMember
.
- Through the class name:
Code Example:
File: counter.h
#ifndef COUNTER
#define COUNTER
class Counter {
private:
static int count;
public:
Counter();
};
#endif
File: counter.cpp
#include "counter.h"
Counter::Counter() {
count++;
}
int Counter::count = 0;
int main() {
Counter c1;
}
Static Member Functions
- No this Pointer: Static member functions cannot access non-static data members directly because they do not have an implicit
this
pointer. - Class-Level Operations: Typically used for utility functions that affect the class as a whole (e.g., counting instances, maintaining global state).
- Access:
- Through the class name:
ClassName::staticFunction()
. - Through an instance:
objectName.staticFunction()
(though using the class name is clearer).
Code Example:
File: counter.h
#ifndef COUNTER
#define COUNTER
class Counter {
private:
static int count;
public:
Counter();
static void showCount();
};
#endif
File: counter.cpp
#include <iostream>
#include "counter.h"
Counter::Counter() {
count++;
}
void Counter::showCount() {
std::cout << "Number of Counter objects: " << count << std::endl;
}
int Counter::count = 0;
int main() {
Counter c1;
Counter c2;
Counter::showCount(); // Output: Number of Counter objects: 2
Counter c3;
Counter::showCount(); // Output: Number of Counter objects: 3
}
Friend Functions
- Definition: A friend function is a non-member function that has access to the private and protected members of a class.
- Declaration: Declared with the
friend
keyword inside the class. - Advantages: Allows certain external functions to have intimate knowledge of a class’s internals without making those internals public.
- Limitations: Does not violate encapsulation if used judiciously, but can reduce maintainability if overused.
Code Example:
File: box.h
#ifndef BOX
#define BOX
class Box {
private:
double length;
double width;
double height;
friend double getVolume(const Box&);
public:
Box(double l, double w, double h)
};
#endif
File: box.cpp
#include <iostream>
#include "box.h"
Box::Box(double l, double w, double h) : length(l), width(w), height(h) {}
double getVolume(const Box& b) {
return b.length * b.width * b.height;
}
int main() {
Box box(3.0, 4.0, 5.0);
std::cout << "Volume: " << getVolume(box) << std::endl;
}
Friend Classes
- Definition: One class can be declared as a friend of another, giving it access to the friend class’s private and protected members.
- Usage:
- Useful when two or more classes need to cooperate closely, sharing implementation details.
- Should be used sparingly to avoid excessive coupling.
Code Example:
File: alpha.h
#ifndef ALPHA
#define ALPHA
class Alpha;
class Alpha {
private:
int data;
friend class Beta;
public:
Alpha(int value);
};
#endif
File: beta.h
#ifndef BETA
#define BETA
class Beta {
private:
int data;
public:
Beta(int value);
void showAlphaData(const Alpha& a);
};
#endif
File: main.cpp
#include <iostream>
#include "alpha.h"
#include "beta.h"
Alpha::Alpha(int value) : data(value) {}
Beta::Beta(int value) : data(value) {}
void Beta::showAlphaData(const Alpha& a) {
std::cout << "Alpha's data = " << a.data << std::endl;
}
int main() {
Alpha alpha(42);
Beta beta;
beta.showAlphaData(alpha);
}