static members, friends and inner classes

Keywords: C++

1, static member

1. Concept: class members declared as static become static members of the class.
Member variables decorated with static are called static member variables,
Member functions decorated with static are called static member functions.

class Test {
public:
	//Test():m_a(0){}
	Test():m_b(0){
	}
	//Static functions do not have this pointer
	static void fun() {//Static functions can only call static members, not ordinary members
		m_a = 0;
		//show(); Cannot call
	}
	void show() {//Ordinary functions can call ordinary members and static members
		m_b = 0;
		m_a = 0;
		fun();
	}
private:
	static int m_a;//Static members cannot be initialized inside the class in the form of parameter list, but only outside the class
	int m_b;
};
int Test::m_a = 0;//Class name + scope resolver is used during initialization
void main() {
	Test t;
}

2. Characteristics:

  • Static members are shared by all class objects and do not belong to a specific instance
  • Static member variables must be defined outside the class without adding the static keyword
  • Class static members can be accessed by class name:: static member or object. Static member
  • Static member functions have no hidden this pointer and cannot access any non static members
  • Static members also have access levels in public, protected and private, and can also have return values

2, Friends

Friends are divided into friend functions and friend classes
1. Friend function: a class independent function can be used to enable its class object to directly access private members in the class

class Test {
	friend void fun(const Test &t);
	friend ostream& operator<<(ostream& out, const Test &d);
public:
	Test(int data = 0) {
		m_data = data;
	}
	int GetData()const {
		return m_data;
	}
private:
	int m_data;
};
void fun(const Test &t) {
	int data = t.m_data;//Make the void fun() function a friend function to access m directly_ data
}
ostream& operator<<(ostream& out, const Test &d) {
	out << d.m_data;
	return out;
}

int main() {
	Test t(10);
	fun(t);
	cout << "t = " << t << endl;
	return 0;
}

Note: because the output stream object of cout and the implied this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, which is the left operand. However, in actual use, cout needs to be the first formal parameter object to be used normally. So we need to overload operator < < into a global function. But in this case, there will be no way to access members outside the class, so friends are needed to solve it.

A friend function can directly access the private members of a class. It is an ordinary function defined outside the class and does not belong to any class, but it needs to be declared inside the class. The friend keyword needs to be added when declaring

explain:

  • Friend functions can access private and protected members of a class, but they are not member functions of a class
  • Friend functions cannot be modified with const
  • Friend functions can be declared anywhere in the class and are not restricted by the class access qualifier
  • A function can be a friend function of multiple classes
class A {
	friend void fun(const Test &t, const A &a);
private:
	int m_a = 0;
};
class Test {
	friend void fun(const Test &t, const A &a);
	friend ostream& operator<<(ostream &out, const Test &t);
	friend istream& operator>>(istream &in, Test &t);
public:
	Test(int data = 0) :m_data(data) {}
	~Test() {}
private:
	int m_data;
};
void fun(const Test &t, const A &a) {//A function can be a friend function of multiple classes
	cout << "data = " << t.m_data << endl;
}
ostream& operator<<(ostream &out, const Test &t) {
	out << t.m_data;
	return out;
}
istream& operator>>(istream &in, Test &t) {
	in >> t.m_data;
	return in;
}
void main() {
	Test t;
	A a;
	cin >> t;
	cout << "t = " << t << endl;
}

2. Friend class: all member functions of a friend class can be friend functions of another class and can access non-public members of another class

characteristic:

  • Friend relationship is unidirectional and not exchangeable
class List;//forward declaration 
class ListNode {
	friend class List;//Friend class
public:
	ListNode():m_data(0),m_next(nullptr)
	{}
	~ListNode()
	{}
public:
	void fun() {
		List t;
		//Friend relationship is unidirectional and not exchangeable
		cout << t.m_head << endl;//t uses an undefined class"List"
	}
private:
	int m_data;
	ListNode *m_next;
};
class List {
public:
	List() :m_head(nullptr)
	{}
	~List()
	{}
public:
	void push_front(int v) {
		ListNode *s = (ListNode*)malloc(sizeof(ListNode));
		assert(s != NULL);
		s->m_data = v;
		s->m_next = nullptr;
		s->m_next = m_head;
		m_head = s;
	}
	void show_list() const {
		ListNode *p = m_head;
		while (p != nullptr) {
			cout << p->m_data << "-->";
			p = p->m_next;
		}
		cout << "Over." << endl;
	}
private:
	ListNode *m_head;
};
int main() {
	List myList;
	for (int i = 1; i <= 10; ++i) {
		myList.push_front(i);
	}
	myList.show_list();
	return 0;
}
  • Friend class cannot be passed
class A{
	friend class B;
	......
};
class B{
	friend class C;
	......
};
class C{
	A;//Cannot access
};

3, Inner class

1. Concept: if a class is defined inside another class, it is called an inner class

class List {//External class
public:
	class iterator {//Inner class
	public:
		void show()const {
			cout << "List::iterator::show()." << endl;
			List lt;
			lt.m_a = 10;//The inner class can access all members in the outer class through the object parameters of the outer class
		}
	private:
		int m_c = 0;
	};
private:
	int m_a = 0;
	int m_b = 0;
};
void main() {
	//List::iterator it;
	//it.show();
	cout << sizeof(List) << endl;
}

Note: the inner class is the friend class of the outer class. Note the definition of the friend class. The inner class can access all members of the outer class through the object parameters of the outer class. But the outer class is not a friend of the inner class.
2. Characteristics:

  • Internal classes can be defined in public, protected and private of external classes
  • The internal class can directly access the static and enumeration members in the external class without the object / class name of the external class
  • sizeof (external class) = external class, which has nothing to do with internal class
    The above code obtains sizeof (List) = 8, i.e. m_a occupies 4 bytes, m_b takes up 4 bytes, a total of 8 bytes, independent of the internal class

Posted by fuzzy1 on Sun, 31 Oct 2021 08:12:40 -0700