Skip to content

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.

C++
struct point{
  float x;
  float y;
  void init(int x, int y){
    this->x=x;
    this->y=y;
  }
  void print(){
    cout << x << ", " << y <<endl;
  }
}
C++
class point{
private:
  float x;
  float y; //the above data is protected.

public://the followings can be accessed from outside
  void init(int x, int y){
    this->x=x;
    this->y=y;
  }
  void print(){
    cout << x << ", " << y <<endl;
  }
}

Object | an instance of class

C’tor (constructor)

  • Initialization List

C++
class A{
  private:
    int i;
    int j= i;

  public:
    A():i(11){}
}
Initialization versus Assignment

C++
Stu::Stu(string s):name(s){} // better to use
Stu::Stu(string s){name=s;}
Equivalent:

C++
string place(Hangzhou);
string place = Hangzhou;

int i = 6;
int i(6); 

A constructor function:

C++
point::point(int x, int y){
  this->x=x;
  this->y=y;
}
then use it:

C++
point a(1,2);
And if the constructor function only takes in one parameter, like

C++
point::point(int dep){
  this->x=this->y=dep;
}
then we can use it to initialize:

C++
point a(1);
point a=10;
we can not initialize a point like we do in struct:

C++
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.

C++
struct Y{
  float y;
  int i;
  Y(int a);
}
then:

C++
Y y1[] = {Y(1), Y(2)}; // right
Y y2[2] {Y(1)}; // wrong
Y y3[7]; //wrong
Y y4;  //wrong

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)

C++
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

C++
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:

C++
int harpo(int n, int m, int j=5);
int chico(int n, int m=6, int j); //illegal

default argument must be written in declaration, i.e. in ".h" file. We can not write it in definition, but always in calling back.

C++
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.

C++
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.

C++
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

C++
// 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

C++
class Tv;
class Remote{...}; // Tv0using methods declaration without definition.
class Tv{...};

inline function | 内联

It can check the type, which is better than Macro(宏)!

C++
inline double square(double x);
inline double square(double x){ return x*x;}
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 立即数)

C++
const int a = 6; 
  • literal -> 6
  • constant -> a

Distinguish:

C++
String p1(Fred);
const string * p = &p1; //(1)
string const * p = &p1; //(2)
string * const p = &p1; //(3)

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.

C++
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

C++
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.

C++
class A {
private:
  int i=0;
public:
  void f() {i=10;
    cout << A::f()<< end;
  }
  void f() const {
    cout << A::f() const<< end;
  }
}
The above means:

C++
public:
  void f(A *this) {i=10;
    cout << A::f()<< end;
  }
  void f(const A *this) const {
    cout << A::f() const<< end;
  }

So:

C++
const A a;
A b;
a.f(); // <<“A::f() const”
b.f(); // <<“A::f()”
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!

C++
static int i; // can be accessed by all the objects of same class
we must define the static variable (global variable) before main!

C++
int A::i = 0;
Note: without static!

C++
static void sf(){
  i++;
}
we can call static function without creating an object! Just use class!

C++
int main(){
  A::sf();
}

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.

C++
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.

C++
z = 3 + 7; // pass 10 to initialize z

= () [] -> ->* must be members and all other binary operators(双目) should be non-members.

Will the operator change the operation number?

  • If not, use const.
Common Operators
// + - * / % ^ & | ~
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
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;
}