[!Important] Difference
Scope:Scope means visibility, which considers the ability whether the complier can recognize a variable/structure/function.
Access Control
Access control is the ability that whether a code can access(modify) a variable/structure/…
C entangles information hiding with file management, offering a few choices for scope: file/global/compound statement.
And scope implies access control in C, as long as the complier can recognize the code(can track them in its stack frame), the code can modify the data by name.
Dilemma: If we want to implement module design, which means share information among several files, we sometimes have to jam all modules into a single file(In this case, the code can recognize the variables)
Considering the incapability of module design and extensibility in C, C++ decouples access control from scope.
[!Important] Access rights in C++
Access rights in C++ are granted by a class and are specified in the class’s definition.
Scope is only visibility in C++ and does not grant access rights.
[!Note] Ability & Inability of Access control in C++
AbilityA class can allow another class to access specific fields of any instance or to call specific functions.
Inability
Access rights to specific instances are not controllable, which means we can’t control the concrete access rights to a specified instance of a certain class
即 C++ 中的访问权限均在类的维度上操作,我们可以声明对类中具体的子项的访问权限,但不能更改一个孤立的类的项的访问权限
In C++ code, since access rights can be managed explicitly, all class definitions are globally visible -> Better extensibility when implementing module design
In C++, the scope resolution operator is used for specify which scope and namespace to access.
Usage:
Scope resolution operator in C++
[!Info] Friends
Classes can have friends, which are functions or classes that are granted access to its private and protected member. This is done by friend keyword.
Notice:
Friend functions are in the global namespace, not in the class, so access control has no relevance. Its return type is often the whole instance.
- Friend function could be either global function or other class member function
friend return_type func_name (arguments)
for global functionfriend return_type class_name::funcname (arguments)
for a member function of another function
- Declare a friend class
friend class friendname
- Friendship is not mutual, and friendship is not inherited.
^72a29f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass {
private:
int privateVar;
//We can also declare a friend by friend keyword
friend class F;
public:
friend void accessPrivate( MyClass& obj );
//MyClass& means reference, similar to pointer
};
void accessPrivate( MyClass& obj ) {
// Allowed to access obj's privateVar
obj.privateVar = 10;
}
Constructor and destructors are both member functions with implicit this pointer.
Constructors are used for initializing a class member, which are often declared as public access right.
[!Note] Called time
- Automatic variables(called at point of declaration)
- Static variables(called before main)
- Dynamic variables(at point of allocation)
NoticeConstructors are always called for initialization, 任意的 class instance declare 过程一定会调用 construtor,注意与赋值时可能会重载的赋值运算符区分!!
Common Features of Constructors:
Two public constructors are created by default
The constructor with no arguments created only if no constructors declared in class definition used for initializing array elements. Array of a class’ instances are not allowed if no constructor with no arguments exists
operation
It initializes each field based on its type,对一般的变量填 bits,对 instance 调用相应的 constructor
It takes one argument: a reference* to another instance of the same class,注意 copy constructor 经常接受 const reference 型的参数防止更改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
class Sample {
int id;
public:
Sample(int x) { id = x; }
Sample(const Sample &t){
id = t.id;
}
void display() { cout << "ID=" << id; }
};
int main()
{
Sample obj1(10);
obj1.display();
cout << endl;
//Emplicit copy constructor calling
Sample obj2(obj1); // or obj2=obj1;
obj2.display();
return 0;
}
[!Important] Concept
A brief specification for initialization, consisting of a base class or field name and an arbitrary expression in parentheses
For base classes and instances, lists of expression are passed to constructors.
Order of initializer does not affect code, but should match the order of execution
1
2
3
4
5
6
7
class MyClass {
public:
MyClass(int val) : value(val) {} // Using an initializer list
private:
int value;
};
MyClass obj(42); // 'value' is initialized with 42 using the initializer list
The initializer list and the constructor declaration are separated by :
.
A constructor can’t be inherited
[!Important] Concept
A destructor is a special member function of a class that is called to clean up an object when it is no longer needed.
Its purpose is to release resources that the object may have acquired during its lifetime, such as memory, file handles, network connections, etc.
The destructor is defined with the~
prefix followed by the class name and does not have a return type or parameters.
[!Note] Called time
- Automatic variables: at the end of scope
- Static variables: after main
- Dynamic variables: at the point of deallocation
Not called cases:When the program abnormally terminates or dynamically allocated instances that are not deallocated
Operation order
The order of implemening destructor is the reverse order of constructor.
[!Warning] define destructor and make it virtual
In a hierarchy of classes, derived classes may allocate resources that need to be released explicitly. A virtual destructor ensures that the destructor chain is properly executed, starting from the most derived class up to the base class. This allows each class to clean up its own resources.
In sum it can keep consistency when encountering unmatched but need to be accurate types
Don’t call destructor for fields that are instances, such calls are made automatically, but we must call destructor for dynamically allocated variables
1
2
3
4
5
6
class MyClass {
public:
~MyClass() {
// Clean-up code here
}
};
How objects look at functions and data members of a class
[!tip] Availability
- “this” pointer is passed as a hidden argument to all nonstatic member function calls and is available as a local variable within the body of all nonstatic functions.
- It is non available in static member functions as static member functions can be called without any object.
- 注意在 LC3 的 stack frame 中可以作为 non static member function 的隐藏变量!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1(5, 5);
// Chained function calls. All calls modify the same object
// as the same object is returned by reference
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
[!Important] Virtual function
A virtual function (also known as virtual methods) is a member function that is declared within a base class and is re-defined (overridden) by a derived class.When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s version of the method.
In sum: Allow for polymorphism for a class cluster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
class base {
public:
virtual void print() { cout << "print base class\n"; }
void show() { cout << "show base class\n"; }
};
class derived : public base {
public:
void print() { cout << "print derived class\n"; }
void show() { cout << "show derived class\n"; }
};
int main()
{
base* bptr;
derived d;
bptr = &d;
// Virtual function, binded at runtime
bptr->print();
// Non-virtual function, binded at compile time
bptr->show();
return 0;
}