Class & Object¶
Class(Struct)¶
Intuitively, we put a function into a struct
and it bacome class
.(we can use functional point in C)
act like a type.
- Definition We all know the principle of designing:
separated .h &.cpp are used to define one class
-
Header file(.h): class declaration&prototype
-
Source file(.cpp): all the bodies of functions
Hidden parameter: this
, which is a pointer to the variable.
Object | an instance of class¶
C’tor (constructor)¶
- Initialization List
A constructor function:
then use it: And if the constructor function only takes in one parameter, like then we can use it to initialize: we can not initialize a point like we do in struct:point a ={1,2}; // this can succeed only when the class does not have a constructor function and the parameter is public.
- Default Constructor
It is a function that can be called with no arguments input.
If we don’t give any constructor function, then the system can give one that does nothing.
If we offer a constructor function that takes input of more than one parameter, we have no default constructor function.
then:D’tor(destructor)¶
This function would be implemented before the memory is recycled.
To design it, please add tilde ~
before the name of the class. The function have no input and output.
It will delete local objects in a reverse manner.(caused by stack action)
class point{
private:
float x;
float y;
//the above data is protected.
public://can be accessed from outside
point(int dep); // reload
point(int x, int y);
~point();
void print();
}
Using Class¶
Function overloading¶
For function with the same name, compiler will choose from different function according to different input/labels.
Pay attention to primitive type input
void f(int i){}
void f(double d){}
int main() {
f(‘a’); //despite smaller than int, it can be transformed
f(2); // ambiguous
f(2L); // ambiguous
f(3.2); // ok
}
Default argument¶
we should give default argument from right to left:
default argument must be written in declaration, i.e. in ".h" file. We can not write it in definition, but always in calling back.
void fun(int a, int b = 1, char c = 'a'); // 声明中指定默认参数
void fun(int a, int b, char c) { // 定义中不能再指定默认参数
...// 函数实现
}
Friend¶
A declaration, which cannot append.
Two classes can be a friend relationship when they cannot be "is-a"(public inheritance) or "has-a"(embedding), like Tv and remote.
class Tv
{
friend class Remote; // a class Remote can access all the private member functions/variables of Tv.
}
In fact, a class can use member functions of another class to achieve some usage, not by accessing directly its member variables. Only some functions must access these member variables.
class Tv
{
friend void Remote::set_chan(Tv &t, int c); // here only this function can affect private member variables of Tv.
// compiler need to first know Remote class.
};
So
// this is right:
class Tv; //forward declaration
class Remote{...}; // Remote::set_chan declaration
class Tv{...};
// this is wrong
class Remote; // forward declaration
class Tv{...}; // Tv declaration in which we have set_chan which has not been declared.
class Remote{...};
But if Remote
has inline function which calls a function of Tv
, the above right forward declaration does not work. So the solution becomes
inline function | 内联¶
It can check the type, which is better than Macro(宏)!
is only a declaration instead of a definition, so the compiler must see the body of function!- compiler must see body so it can compile!(not just write down as a declaration)
Body of inline function must be put in ".h" files so it can be used in another file!
- if you write a inline function in a ".cpp" file, you mean the function should only be used locally.
Function that can be used inline
Function that can be used inline
:
- small function
- frequently called function
others that cannot be used inline
:
- long function
- recursive function
类的内联函数可以在类体内定义,此时不需要显式使用 inline 关键字。如果选择在类体外定义,则需要使用 inline 关键字。
Const¶
constants are variables - (instant 立即数)
- literal -> 6
- constant -> a
Distinguish:
Const only restrict one variable.
(1)(2) are the same: (*p)
can not change; That is, we cannot change p1
through (*p)
.
(3) means the pointer p
itself cannot change but p1 itself can still change.
int i;
const int ci = 3;
int *ip = &i;
int *ip = &ci; // illegal, that is, a changeable pointer now points a non-changeable variable, which is illegal in compiler.
const int * cip = &i;
const int * cip = &ci;
- Passing & returning by const value
We do this in case that we change some value in a function. So we let compiler check.
- Const object
in a function, we pass a pointer instead of a copy!
(1) public
(2) change value by inner function
int get_day(void) const;
int get_day(void) const {return day;}
const A a; // must provide a an initial value!(or constructor) because later we cannot change it! Like below:
const int i=1; // we cannot do this before C11
public:
A(int k): i(k){}
- constant i cannot change during execution, but need a value in initialization.
class A {
private:
int i=0;
public:
void f() {i=10;
cout << “A::f()”<< end;
}
void f() const {
cout << “A::f() const”<< end;
}
}
public:
void f(A *this) {i=10;
cout << “A::f()”<< end;
}
void f(const A *this) const {
cout << “A::f() const”<< end;
}
So:
The above code is using overload, and there are two different f() that have been distinguished by “const”.So a const object can only use function attached to "const" and cannot use function with no "const".
Static¶
on members which are
- Hidden
- Persistent
static variable is actually global variable.
static function can only access static variable!
we must define the static variable (global variable) before main! Note: without static! we can call static function without creating an object! Just use class!We can eliminate global variable because we can limit it in class, which can prevent arbitrary changes!
Overloaded Operator¶
operators of primitive class cannot be changed.
Integer x(1), y(2);
z = x + y // x.operator+(y)
z = x + 3 // x.operator+(Interger(3))
z = 3 + x // not allowed
Global operator.
= () [] -> ->*
must be members and all other binary operators(双目) should be non-members.
Will the operator change the operation number?
- If not, use
const
.
// + - * / % ^ & | ~
const T operatorX(const T&I, const T&L)
// ! && || < <= == >= >
bool operatorX(const T&I, const T&L)
// []
E& T::operator[](int index);
// prefix ++ -- e.g. ++a
const Integer& Integer::operator++(){
*this +=1;
return *this; // reference for old one, without copying new
}
// postfix ++ -- e.g. a++
const Integer& Integer::operator++(int){
Integer old(*this);
++(*this);
return old;
}
// Relational operators
bool Integer::operator==(const Integer & rhs) const{
return i == rhs.i;
}
bool Integer::operator!=(const Integer & rhs) const{
return !(*this == rhs);
}
bool Integer::operator<(const Integer & rhs) const{
return !(i < rhs.i);
}
bool Integer::operator>(const Integer & rhs) const{
return rhs < *this;
}
bool Integer::operator<=(const Integer & rhs) const{
return !(rhs < *this);
}
bool Integer::operator>=(const Integer & rhs) const{
return !(*this < rhs);
}
// operator [] must be member function, single argument
- Extractor & Inserter
// stream extractor cin >>: global function
operator>>(istream &is, T& obj){
// ...
return is; // always this
}
cin >> a >> b // ((cin >> a ) >> b)
// stream inserter cout <<: global function
operator<<(ostream& os, const T& obj){
// ...
return os;
}
- Assignment
=
// member function
// usually before calling "=" the object being assigned already has had sth.
T & T::operator=(const T & rhs){
// check for self assignment
if(*this != ths) // otherwise will cause error (you will delete allocated memory and new one according to the deleted memory)
{
// ...
}
return *this;
}