forked from Light-City/CPlusPlusThings
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Light-City#54 from xliu79/english
english
- Loading branch information
Showing
167 changed files
with
6,508 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# Pure virtual functions and abstract classes | ||
|
||
## About Author: | ||
|
||
|
||
|
||
![](../img/wechat.jpg) | ||
|
||
## 1.Pure virtual function and abstract class | ||
|
||
|
||
Pure virtual functions (or abstract functions) in C + + are virtual functions that we have not implemented!We just need to state it! | ||
example: | ||
```cpp | ||
// abstract class | ||
Class A { | ||
public: | ||
virtual void show() = 0; // pure virtual function | ||
/* Other members */ | ||
}; | ||
``` | ||
|
||
* Pure virtual function: virtual function without function body | ||
* Abstract classes: classes containing pure virtual functions | ||
|
||
Abstract classes can only be used as base classes to derive new classes. Objects, pointers and references of abstract classes cannot be created->An object of a class derived from an abstract class! | ||
|
||
> Code example:[test.cpp](./test.cpp)、[pure_virtual.cpp](./pure_virtual.cpp) | ||
## 2.Implement abstract classes | ||
|
||
Abstract class:Pure virtual functions can be called within member functions.Pure virtual functions cannot be used inside constructors / destructors. | ||
|
||
If a class derives from an abstract class, it must implement all pure virtual functions in the base class to become a non abstract class. | ||
```cpp | ||
// A is abstract class | ||
class A { | ||
public: | ||
virtual void f() = 0; // pure virtual function | ||
void g(){ this->f(); } | ||
A(){} // 构造函数 | ||
}; | ||
|
||
class B : public A{ | ||
public: | ||
void f(){ cout<<"B:f()"<<endl;} // 实现了抽象类的纯虚函数 | ||
}; | ||
``` | ||
> Code Example:[abstract.cpp](./abstract.cpp) | ||
## 3.Key point | ||
- [Pure virtual functions make a class abstract](./interesting_facts1.cpp) | ||
```cpp | ||
// Abstract class contains at least one pure virtual function | ||
class Base{ | ||
public: | ||
virtual void show() = 0; // 纯虚函数 | ||
int getX() { return x; } // 普通成员函数 | ||
private: | ||
int x; | ||
}; | ||
``` | ||
|
||
- [Pointers and references to abstract class types](./interesting_facts2.cpp) | ||
```cpp | ||
class Derived : public Base { | ||
public: | ||
void show() { cout << "In Derived \n"; } // 实现抽象类的纯虚函数 | ||
Derived(){} // 构造函数 | ||
}; | ||
|
||
int main(void) | ||
{ | ||
//Base b; // error! 不能创建抽象类的对象 | ||
//Base *b = new Base(); error! | ||
|
||
Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象 | ||
bp->show(); | ||
return 0; | ||
} | ||
``` | ||
- [If we do not override pure virtual functions in the derived class, the derived class will also become an abstract class](./interesting_facts3.cpp) | ||
```cpp | ||
// Derived为抽象类 | ||
class Derived: public Base | ||
{ | ||
public: | ||
// void show() {} | ||
}; | ||
``` | ||
|
||
- [Abstract classes can have constructors](./interesting_facts4.cpp) | ||
```cpp | ||
// abstract class | ||
class Base { | ||
protected: | ||
int x; | ||
public: | ||
virtual void fun() = 0; | ||
Base(int i) { x = i; } // constructor function | ||
}; | ||
// 派生类 | ||
class Derived: public Base | ||
{ | ||
int y; | ||
public: | ||
Derived(int i, int j) : Base(i) { y = j; } // constructor function | ||
void fun() { cout << "x = " << x << ", y = " << y; } | ||
}; | ||
``` | ||
|
||
- [A constructor cannot be a virtual function, and a destructor can be a virtual destructor](./interesting_facts5.cpp) | ||
```cpp | ||
// 抽象类 | ||
class Base { | ||
public: | ||
Base(){ cout << "Constructor: Base" << endl; } | ||
virtual ~Base(){ cout << "Destructor : Base" << endl; } | ||
|
||
virtual void func() = 0; | ||
}; | ||
|
||
class Derived: public Base { | ||
public: | ||
Derived(){ cout << "Constructor: Derived" << endl; } | ||
~Derived(){ cout << "Destructor : Derived" << endl;} | ||
|
||
void func(){cout << "In Derived.func()." << endl;} | ||
}; | ||
``` | ||
>When the base class pointer points to a derived class object and removes the object, we may want to call the appropriate destructor. | ||
>The destructor can only be called if it is not a virtual destructor. | ||
## 4.Complete example | ||
Abstract classes are inherited and implemented by derived classes! | ||
> Code Example:[derived_full.cpp](./derived_full.cpp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* @file abstract.cpp | ||
* @brief 抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数 | ||
* 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
class A { | ||
public: | ||
virtual void f() = 0; // 纯虚函数 | ||
void g(){ this->f(); } | ||
A(){} | ||
}; | ||
class B:public A{ | ||
public: | ||
void f(){ cout<<"B:f()"<<endl;} | ||
}; | ||
int main(){ | ||
B b; | ||
b.g(); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/** | ||
* @file derived_full.cpp | ||
* @brief 完整示例!抽象类由派生类继承实现! | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
class Base | ||
{ | ||
int x; | ||
public: | ||
virtual void fun() = 0; | ||
int getX() { return x; } | ||
}; | ||
|
||
class Derived: public Base | ||
{ | ||
int y; | ||
public: | ||
void fun() { cout << "fun() called"; } // 实现了fun()函数 | ||
}; | ||
|
||
int main(void) | ||
{ | ||
Derived d; | ||
d.fun(); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* @file interesting_facts1.cpp | ||
* @brief 纯虚函数使一个类变成抽象类 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
/** | ||
* @brief 抽象类至少包含一个纯虚函数 | ||
*/ | ||
class Test | ||
{ | ||
int x; | ||
public: | ||
virtual void show() = 0; | ||
int getX() { return x; } | ||
}; | ||
|
||
int main(void) | ||
{ | ||
Test t; //error! 不能创建抽象类的对象 | ||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* @file interesting_facts2.cpp | ||
* @brief 抽象类类型的指针和引用 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
|
||
/** | ||
* @brief 抽象类至少包含一个纯虚函数 | ||
*/ | ||
class Base | ||
{ | ||
int x; | ||
public: | ||
virtual void show() = 0; | ||
int getX() { return x; } | ||
|
||
}; | ||
class Derived: public Base | ||
{ | ||
public: | ||
void show() { cout << "In Derived \n"; } | ||
Derived(){} | ||
}; | ||
int main(void) | ||
{ | ||
//Base b; //error! 不能创建抽象类的对象 | ||
//Base *b = new Base(); error! | ||
Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象 | ||
bp->show(); | ||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* @file interesting_facts3.cpp | ||
* @brief 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类。 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
class Base | ||
{ | ||
int x; | ||
public: | ||
virtual void show() = 0; | ||
int getX() { return x; } | ||
}; | ||
class Derived: public Base | ||
{ | ||
public: | ||
// void show() { } | ||
}; | ||
int main(void) | ||
{ | ||
Derived d; //error! 派生类没有实现纯虚函数,那么派生类也会变为抽象类,不能创建抽象类的对象 | ||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/** | ||
* @file interesting_facts4.cpp | ||
* @brief 抽象类可以有构造函数 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
|
||
#include<iostream> | ||
using namespace std; | ||
|
||
// An abstract class with constructor | ||
class Base | ||
{ | ||
protected: | ||
int x; | ||
public: | ||
virtual void fun() = 0; | ||
Base(int i) { x = i; } | ||
}; | ||
|
||
class Derived: public Base | ||
{ | ||
int y; | ||
public: | ||
Derived(int i, int j):Base(i) { y = j; } | ||
void fun() { cout << "x = " << x << ", y = " << y; } | ||
}; | ||
|
||
int main(void) | ||
{ | ||
Derived d(4, 5); | ||
d.fun(); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
/** | ||
* @file interesting_facts5.cpp | ||
* @brief 构造函数不能是虚函数,而析构函数可以是虚析构函数。 | ||
* 例如:当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类析构函数。 | ||
* @author 光城 | ||
* @version v1 | ||
* @date 2019-07-20 | ||
*/ | ||
#include<iostream> | ||
using namespace std; | ||
|
||
class Base { | ||
public: | ||
Base() { cout << "Constructor: Base" << endl; } | ||
virtual ~Base() { cout << "Destructor : Base" << endl; } | ||
}; | ||
|
||
class Derived: public Base { | ||
public: | ||
Derived() { cout << "Constructor: Derived" << endl; } | ||
~Derived() { cout << "Destructor : Derived" << endl; } | ||
}; | ||
|
||
int main() { | ||
Base *Var = new Derived(); | ||
delete Var; | ||
return 0; | ||
} | ||
|
Oops, something went wrong.