OOP Study Record

1. Friend

Key word: friend, can let a function or class access the private member in another class.

1.1 Global function as the friend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class house
{
friend void goodgay(house *house);

public:
house()
{
m_sittingroom = 's';
m_bedroom = 'b';
}

char m_sittingroom;

private:
char m_bedroom;
};
1
2
3
4
5
//Global function
void goodgay(house *house)
{
cout << house->m_sittingroom << house->bedroom << endl;
}

The global function, add friend void goodgay(house *house); in any place when declare a class, the function can access the private member.

1.2 Class as the friend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class building{};

class goodgay
{
public:
void visit(); //access public & private in building class
goodgay();

building *b;
};

class building
{

friend class goodgay;

public:
building();

char m_sittingroom;

private:
char m_bedroom;
};

//declare the member function out the class
building::building()
{
m_sittingroom = 's';
m_bedroom = 'b';
}

goodgay::gay()
{
//create building obj
//building *b; in goodgay class
b = new building;
}

void goodgay::visit()
{
out << b->m_sittingroom << '\n';
}
1
2
3
4
5
void test() 
{
goodgay gg;
gg.visit();
}

This example mainly describes how to declare member function out of the class.

1.3. Member function as the friend

friend void goodgay::visit();, declare out of the class.

2. Member Feature

2.1 Member Variable & Member function

1
2
3
4
5
class x
{

};

An empty obj consumes one byte memory.

1
2
3
4
5
6
7
class x
{
int m_x1; // not static
static int m_x2; // static
void fun() {}
};

If an obj is not empty, for example the upper class consumes 4 byte as the static variable is not belonged to the class and the member function is saved separately , which not belongs to the obj of the class either.

2.2 This Pointer

The this pointer points to the invoked obj of the class, solves the name conflict and return the obj itself.

2.2.1 Solve the Name Conflict

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Example
{
public:
Example(int num)
{
num = num;
} // this is the wrong constructor function

Example(int num)
{
this->num = num;
}// this one is right

int num;
};
1
2
3
4
5
6

void test01()
{
Example ex(10);
std::cout << ex.num;
}

2.2.2 Return the Obj Itself

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Example
{
public:
Example(int num)
{
this->num = num;
}

void ExampleAddNum(Example &in_ex)
{
this->num += in_ex.num
}

int num;
};
1
2
3
4
5
6
void test02()
{
Example ex1 = 10, ex2 = 10;
ex2.ExampleAddNum(ex1);
std::cout << ex2.num;
}

Now the ex2.num is 20;

The down case is a wrong one.

1
2
3
4
5
6
7
void test03()
{
Example ex1 = 10, ex2 = 10;
//The return value is void, the compiler will report error.
ex2.ExampleAddNum(ex1).ExampleAddNum(ex1).ExampleAddNum(ex1);
std::cout << ex2.num;
}

If you want to add multiple times, you need to return the this pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Example
{
public:
Example(int num)
{
this->num = num;
}

/*you need to return the & else the condition will be like
the first time: ex2`.ExampleAddNum(ex1).ExampleAddNum(ex1)
the second time: ex2``.ExampleAddNum(ex1)
in other words, each time the function is invoked,
a new ex2(obj) will be generated.
*/
Example& ExampleAddNum(Example &in_ex)
{
this->num += in_ex.num
return *this;
}

int num;
};

2.3 nullptr Access the Member function

In the c++, the nullptr can access the member function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Class Example
{
void ShowClassName()
{
std::cout << "Example\n";
}

void ShowExampleNum()
{
std::cout << m_num << std::endl;
}

int m_num;
};
1
2
3
4
5
6
void test01()
{
Example *p = nullptr;
p->ShowClassName();//will not report error
p->ShowExampleNum();//will report error
}

In the p->ShowExampleNum(); the inputted pointer is nullptr.As the real effect in this function is std::cout << this->m_num << std::endl;.The this pointer is nullptr.
If you do not want the error,you can add if(this == nullptr)return;

2.4. const member function

Const function:

  1. const function cannot change the member attribute
  2. adding the “mutable” key words when decare member attribute, it can be changed in the const function.
    Const obj: can only invokes the const function

2.4.1 Const function

1
2
3
4
5
6
7
8
9
10
11
class Example
{
public:
void showExample() const
{
m_A = 100;
//ACTUALLY it is this->m_A = 100;
}

int m_A;
};

The this pointer is a pointer const, it can not be changed where it points at. The showExample function actually means const Example* const this, the pointed value can thus not be changed.The const added after the function means the point of the pointer is const, so the pointed value can not be changed.

2.4.2 Const obj

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Example
{
public:
void showExample() const
{
m_A = 100;
//ACTUALLY it is this->m_A = 100;
}

void change()
{
m_A = 100;
}

int m_A;
mutable int m_B
};

Now the value of m_B can be changed in the const function.

1
2
3
4
5
6
7
void test()
{
const Example ex;
ex.m_A = 100;//error
ex.m_B = 100;//correct
ex.change();//error
}

The const obj can only invokes the const function.

3. Inheritance

3.1 The basic grammar

subclass ~ derived class
parent class ~ base class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BasePage
{
public:

};

//here is the public Inheritance
class JAVA: public BasePage
{
public:
void content
{
std::cout << "JAVA";
}
};

3.2 Inheritance Way

1
2
3
4
5
6
7
8
9
10
//The parent class
class A
{
public:
int a;
protected:
int b;
private:
int c;
};

3.2.1 Public Inheritance

1
2
3
4
5
6
7
8
9
class B: public A
{
public:
int a;
protected:
int b;
inaccessible:
int c;
};

3.2.2 Protected Inheritance

1
2
3
4
5
6
7
8
9
class C: protected A
{
protected:
int a;
protected:
int b;
inaccessible:
int c;
};

3.2.3 Private Inheritance

1
2
3
4
5
6
7
8
9
class D: private A
{
private:
int a;
private:
int b;
inaccessible:
int c;
};

3.3 The obj model in Inheritance

1
2
3
4
5
6
7
8
9
class A
{
public:
int a;
protected:
int b;
private:
int c;
};

If declare another class

1
2
3
4
5
class B
{
public:
int d;
};

The size of class B is 16 byte, except the static member variable, the private member is hided bt the compiler but is still inherited by the subclass.

3.4 The Constructor and Destructor Sequence

Parent constructor
->Subclass constructor
->Subclass destructor
->Parent destructor

3.5 Process of Same Name Member

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
{
public:
int a = 100;
};

class B: public A
{
public:
int a = 200;
};

void test()
{
B b;
std::cout << b.a;
}

The print consequence will be 200, which is the subclass member variable.If you want to access the parent class member, use b.A::a. When it comes to the same name member function, useb.A::func(), the same as the overloaded function, as the subclass hides the same name function in parent class.

3.6 Process of Same Name Static Member

1
2
3
4
5
6
7
8
9
10
11
12
13
class base
{
public:
static int m_A;
};
int base::m_A = 100;

class sub: public base
{
public:
static int m_A;
};
int sub::m_A = 200;

Access by Obj:

1
2
3
4
5
6
7
void test()
{
sub de;
std::cout << de.m_A << std::endl;
std::cout << de.base::m_A << std::endl;

}

Access by Class Name:

1
2
3
4
5
6
void test()
{
sub de;
std::cout << sub::m_A << std::endl;
std::cout << sub::base::m_A << std::endl;
}

The same as the static member function.

3.7 Multiple Inheritance

1
2
3
4
class A: public B, public C, public D
{

};

This inheritance way is not common in c++, as the same name member is hard to deal with.

3.8 Diamond Inheritance

Detailed talked in the Polymorphism

4. Polymorphism

4.1 Basic Grammar

Tips: The pointer or & can directly point at the Base class obj
Dynamic polymorphism: Address late binding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Animal
{
public:
void speak()
{
std::cout << "Animal Talking";
}
};

class Cat: public: Animal
{
public:
void speak()
{
std::cout << "Cat Talking";
}
};
1
2
3
4
5
6
7
8
9
10
11
void do_speak(Animal &an)
{
an.speak();
}
//According to the tips above, you don not need to change the type
//Animal & animal = cat
void test()
{
Cat cat;
do_speak(cat)
}

In this case the result is “Animal talking” as the address is early bound. The func`s address should not be early bound if you want realize different functions.

1
2
3
4
5
6
7
8
9
class Animal
{
public:
//virtual function
virtual void speak()
{
std::cout << "Animal Talking";
}
};

Adding the key word virtualcan realize different function and the address of the speak function is late bound.The sub class need to rewrite the virtual function in the base class.Not overload. When the base class reference(&) or pointer(*) point at the obj of sub class can you use dynamic polymorphism.

4.2 Underlying Principle

1
2
3
4
5
6
7
8
class Animal
{
public:
void speak()
{
std::cout << "Animal Talking";
}
};

sizeof(Animal) = 1.

1
2
3
4
5
6
7
8
class Animal
{
public:
virtual void speak()
{
std::cout << "Animal Talking";
}
};

sizeof(Animal) = 4.
4 bytes ~ virtual function pointer(vfptr). Vfptr contains the Virtual Function Table(vftable) that contains the address of the virtual function.
In the Animal Class, vfptr -> vfable( &Animal::speak( ) ). In the Cat, if the virtual has not been written, then vfptr -> vfable( &Animal::speak( ) ). While the rewritten virtual function covers the virtual function of base class. So now, vfptr -> vfable( &Cat::speak( ) ).

4.3 Abstract Class

If class include more than one(include) Pure Virtual Function, we call te class abstract class.Pure Virtual Function: virtual void func() = 0.

  1. The base class is unable to instantiate.
  2. The sub class must written the pure virtual function.

4.4 Virtual Destruction Function

When using the pointer in base class point at the obj in sub class, the pointer will not do invoke the destruction function in the sub class. By using virtual ~name(), the destruction function will be invoked.
The virtual and pure virtual destruction function ned to be realized as the base class may also have memory in the heap area.

1
2
3
4
5
6
7
8
9
10
class Animal
{
public:
virtual ~Animal() = 0;
}

Animal::~Animal()
{
cout << "The destruction of Animal";
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!