c++ OOP
使用c++演示基本OOP
OOP ?
- 為什麼需要? 我們希望機器能讀懂要做什麼,將程式碼編寫成人類行爲方便閱讀
初探OOP
- 其中最主要的就是纇(Class)這個物件,而在類中,定義類型為最重要的一件事
- 在類中有3個修飾符,分別是private,protected和public,默認為private
- private外界無法訪問(黑色地帶)
- protected介於private和public中間,繼承時用到(灰色地帶)
- product外界可以訪問(白色地帶)
編寫代碼
#include <bits/stdc++.h>
using namespace std;
class Employee{
protected
public:
string Name;
string Company;
int Age;
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Employee employee;
employee.Name = "peter";
employee.Company = "yuntech";
employee.Age = 18;
employee.IntroduceYourSelf();
return 0;
}
存在問題?
- 如果我們今天有100筆資料,修改繁雜且緩慢
- 使用構造函數(Constructors)解決
Constructors
- Constructors遵守3條規則
- 沒有函數返回值,包括void類型定義
- 函數名稱和類名稱相同
- 請將Constructors放在public,他可以放在其他地方但很麻煩
Default Constructors
- 當你沒有編寫任何構造函數時,編譯器會自動編譯
編寫代碼
#include <bits/stdc++.h>
using namespace std;
class Employee{
public:
string Name;
string Company;
int Age;
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Employee employee = Employee("peter","yuntech",18);
employee.IntroduceYourSelf();
return 0;
}
OOP最重要的事情
- 封裝
- 抽象
- 繼承
- 多態性
1.什麼是封裝
- 不希望其他的類可以直接對纇進行操作,將值放入private
- 封裝中主要使用setter和geter方法對值進行操作
#include <bits/stdc++.h>
using namespace std;
class Employee{
private:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Employee employee = Employee("peter","yuntech",0);
employee.IntroduceYourSelf();
employee.SetAge(18);
cout << employee.getAge() << endl;
return 0;
}
2.抽象的概念?
- 當你有像很複雜的產品不希望被人知道他複雜的地方
- 所有繼承了抽象的類都必須實現抽象的方法(虛函數)
#include <bits/stdc++.h>
using namespace std;
class iEmployee{
virtual void AskPromotion() = 0;
};
class Employee:iEmployee{
private:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
void AskPromotion() {
if(Age > 30)
cout << "You can promote" << Age << endl;
else
cout << "You can not promote" << Age << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Employee employee = Employee("peter","yuntech",18);
Employee employee2 = Employee("james","yuntech",40);
employee.AskPromotion();
employee2.AskPromotion();
return 0;
}
3.繼承
- 希望後續的class能擁有其父元素的屬性
#include <bits/stdc++.h>
using namespace std;
class iEmployee{
virtual void AskPromotion() = 0;
};
class Employee:iEmployee{
private:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
void AskPromotion() {
if(Age > 30)
cout << "You can promote" << Age << endl;
else
cout << "You can not promote" << Age << endl;
}
};
class Developer:Employee {
public:
string FavProgrammingLanguage ;
Developer(string Name,string Company,int Age,string favProgrammingLanguage)
: Employee(Name,Company,Age)
{
FavProgrammingLanguage = favProgrammingLanguage;
}
void fixBug(){
cout << getName() << " fix " << FavProgrammingLanguage << " problem " << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Developer d = Developer("peter","yuntech",18,"golang");
d.fixBug();
return 0;
}
發現問題!
- 我們有沒有辦法不要透過getName()來獲得父類別的元素
- 解決:使用protected修飾符號
- 沒有辦法獲得父類別的所有屬性,包括抽象函數
- 解決:繼承時將父類別設為public
#include <bits/stdc++.h>
using namespace std;
class iEmployee{
virtual void AskPromotion() = 0;
};
class Employee:iEmployee{
protected:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
void AskPromotion() {
if(Age > 30)
cout << "You can promote " << Name << endl;
else
cout << "You can not promote " << Name << endl;
}
};
class Developer:public Employee {
public:
string FavProgrammingLanguage ;
Developer(string Name,string Company,int Age,string favProgrammingLanguage)
: Employee(Name,Company,Age)
{
FavProgrammingLanguage = favProgrammingLanguage;
}
void fixBug(){
cout << Name << " fix " << FavProgrammingLanguage << " problem " << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Developer d = Developer("peter","yuntech",18,"golang");
d.fixBug();
d.AskPromotion();
return 0;
}
4.多態性
#include <bits/stdc++.h>
using namespace std;
class iEmployee{
virtual void AskPromotion() = 0;
};
class Employee:iEmployee{
protected:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
void AskPromotion() {
if(Age > 30)
cout << "You can promote " << Name << endl;
else
cout << "You can not promote " << Name << endl;
}
void Work(){
cout << Name << " checking email " << endl;
}
};
class Developer:public Employee {
public:
string FavProgrammingLanguage ;
Developer(string Name,string Company,int Age,string favProgrammingLanguage)
: Employee(Name,Company,Age)
{
FavProgrammingLanguage = favProgrammingLanguage;
}
void fixBug(){
cout << Name << " fix " << FavProgrammingLanguage << " problem " << endl;
}
void Work(){
cout << Name << " coding " << endl;
}
};
class Teacher: public Employee{
public:
string Subject;
Teacher(string Name,string Company,int Age,string subject)
: Employee(Name,Company,Age)
{
Subject = subject;
}
void Prepare(){
cout << Name << " preparing " << Subject;
}
void Work(){
cout << Name << " tech knowledge " << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Developer d = Developer("peter","yuntech",18,"golang");
Teacher t = Teacher("james","yuntech",70,"history");
d.Work();
t.Work();
return 0;
}
多態性常用方法
- 直接使用父類別完成子類別的各種方法
- 遇到還是使用父類別的方法時,可以使用虛擬函數來解決
- 為什麼虛擬函數可以解決?
- 虛擬函數會去檢查最底層的繼承者有沒有使用虛擬函數,如果有的話就使用
#include <bits/stdc++.h>
using namespace std;
class iEmployee{
virtual void AskPromotion() = 0;
};
class Employee:iEmployee{
protected:
string Name;
string Company;
int Age;
public:
void IntroduceYourSelf(){
cout << "Name - " << Name << endl;
cout << "Company - " << Company << endl;
cout << "Age - " << Age << endl;
}
void SetName(string name){
Name = name;
}
void SetCompany(string company){
Company = company;
}
void SetAge(int age ){
//Valid->當false的時候就不會設置
if(age >= 18)
Age = age;
}
string getName(){
return Name;
}
string getCompany(){
return Company;
}
int getAge(){
return Age;
}
Employee(string name,string company,int age){
Name = name;
Company = company;
Age = age;
}
void AskPromotion() {
if(Age > 30)
cout << "You can promote " << Name << endl;
else
cout << "You can not promote " << Name << endl;
}
virtual void Work(){
cout << Name << " checking email " << endl;
}
};
class Developer:public Employee {
public:
string FavProgrammingLanguage ;
Developer(string Name,string Company,int Age,string favProgrammingLanguage)
: Employee(Name,Company,Age)
{
FavProgrammingLanguage = favProgrammingLanguage;
}
void fixBug(){
cout << Name << " fix " << FavProgrammingLanguage << " problem " << endl;
}
void Work(){
cout << Name << " coding " << endl;
}
};
class Teacher: public Employee{
public:
string Subject;
Teacher(string Name,string Company,int Age,string subject)
: Employee(Name,Company,Age)
{
Subject = subject;
}
void Prepare(){
cout << Name << " preparing " << Subject;
}
void Work(){
cout << Name << " tech knowledge " << endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
Developer d = Developer("peter","yuntech",18,"golang");
Teacher t = Teacher("james","yuntech",70,"history");
Employee* e1 = &d;
Employee* e2 = &t;
e1->Work();
e2->Work();
return 0;
}
Friend類
- 當我需要可以使用其他類別的private時,直接引入發現因為private而不可訪問
- 解決:將要調用的類設為friend class
#include <bits/stdc++.h>
using namespace std;
class Home {
private:
string Name;
public:
Home(string name){
Name = name;
}
void member(){
cout << Name << " in home" << endl;
}
friend class Get;
};
class Get{
private:
string Name;
public:
Get(string name){
Name = name;
}
void ISHe(Home h,Get g){
if (h.Name == h.Name)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
};
int main(){
Home h = Home("peter");
h.member();
Get g = Get("peter");
g.ISHe(h,g);
}
運算子多載
- 多載運算子的名稱是 operatorx,其中x是下表中顯示的運算子。例如,若要多載加運算子,您可以定義稱為 operator+的函式。
- 為什麼要運算子多載?
- 當成員元素為private時,只要一多就會需要大量get和set相加,使用運算子多載可以避免這種狀況
- 如何決定運算子參數數量?
- 使用運算子多載以外需要運算的類別
希望實現n1+n2
#include <bits/stdc++.h>
using namespace std;
class Number{
private:
int number;
public:
Number(int num){
number = num;
}
};
int main(){
Number n1 = Number(12);
Number n2 = Number(10);
}
解決
#include <bits/stdc++.h>
using namespace std;
class Number{
private:
int number;
public:
Number(int num){
number = num;
}
Number operator+(Number &n2){
return number + n2.number;
};
int getNumber(){
return number;
}
};
int main(){
Number n1 = Number(12);
Number n2 = Number(10);
Number n3 = n1+n2;
cout << n3.getNumber() << endl;
}
Static和extern
- static能夠讓指定變數跳脫做用域
- extern可以讓變數再不同文件傳輸,宣告了extern的變數等同於在這個文件裡面有一個變數可以用,但是這個變數的宣告並不在此,而是有某個 include 了 此文件的人會去做宣告
如果不使用static
#include <bits/stdc++.h>
using namespace std;
int plusNum(){
int a =0;
++a;
return a;
}
int main(){
for(int i=0;i<5;i++){
cout << plusNum() << endl;
}
}
- 發現a輸出全是1
- 這時候將a設為static,a會從1加到5輸出
#include <bits/stdc++.h>
using namespace std;
int plusNum(){
static int a =0;
++a;
return a;
}
int main(){
for(int i=0;i<5;i++){
cout << plusNum() << endl;
}
}
解構
- 程式執行完的時候自動作用
#include <bits/stdc++.h>
using namespace std;
class Test {
public:
int number;
Test(int num){
number = num;
}
~Test(){
cout << "IS END" << endl;
}
void getNum(){
cout << number << endl;
}
};
int main(){
Test t = Test(10);
t.getNum();
return 0;
}
----
10
IS END