前言
最近項(xiàng)目在開發(fā)涉及到的C++內(nèi)容相對比較多,整理一下,過程中用到的C++面向?qū)ο蟮恼Z法筆記
正文
知識(shí)點(diǎn)的概要
- C++ 類 & 對象
- 值傳遞&引用傳遞
- 拷貝構(gòu)造函數(shù)
- 繼承& 多態(tài)
- 友元
- 模板
- 類型轉(zhuǎn)換
- 異常捕獲
類& 對象
-
C++類定義:本質(zhì)上是定義一個(gè)數(shù)據(jù)類型的合集
類定義是以關(guān)鍵字 class 開頭,后跟類的名稱。類的主體是包含在一對花括號(hào);
class Teacher
{
public:
Teacher(); //構(gòu)造函數(shù) (malloc)
Teacher(int age, char * name); //構(gòu)造函數(shù) (malloc)
~Teacher(); //析構(gòu)函數(shù) 釋放在構(gòu)造函數(shù)里面動(dòng)態(tài)申請的內(nèi)存 (free)
void setAge(int age);
int getAge();
void setName(char *name);
char* getName();
private:
int age;
char *name;
};
-
C++對象的定義
聲明類的對象,就像聲明基本類型的變量一樣
Teacher teacher1; //無參構(gòu)造函數(shù),也可以Teacher teacher1 = Teacher();
Teacher teacher2(28, "kevin"); //有參構(gòu)造函數(shù),創(chuàng)建對象, 也可以Teacher teacher2 = Teacher(28, "kevin");
Teacher *p_teacher = new Teacher(29,"chenyu"); //對象指針,創(chuàng)建可直接new關(guān)鍵字或者下面的方式
Teacher *p_teacher2;
p_teacher2 = &teacher1;
- 完整的例子
Teacher.h:
#pragma once
class Teacher
{
public:
Teacher(); //構(gòu)造函數(shù) (malloc)
Teacher(int age, char * name); //構(gòu)造函數(shù) (malloc)
~Teacher(); //析構(gòu)函數(shù) 釋放在構(gòu)造函數(shù)里面動(dòng)態(tài)申請的內(nèi)存 (free)
void setAge(int age);
int getAge();
void setName(char *name);
char* getName();
private:
int age;
char *name;
};
Teacher.cpp:
#include "Teacher.h"
#include <iostream>
//c++ 標(biāo)準(zhǔn)庫的命名空間
using namespace std;
Teacher::Teacher()
{
cout << " Teacher 構(gòu)造函數(shù) 地址:" << this << endl;
}
Teacher::Teacher(int age, char * name)
{
cout << " Teacher 構(gòu)造函數(shù) 地址:" << this << endl;
this->age = age;
this->name = name;
cout << " Teacher age :" << age << " name :"<< name << endl;
}
Teacher::~Teacher()
{
cout << " Teacher 析構(gòu)函數(shù) 地址:" << this << endl;
}
void Teacher::setAge(int age) {
cout << "Teacher setAge is " << age << endl;
this->age = age;
}
int Teacher::getAge() {
return this->age;
}
void Teacher::setName(char *name) {
cout << " Teacher setName is " << name << endl;
this->name = name;
}
char* Teacher::getName() {
return this->name;
}
main.cpp:
#include "Teacher.h"
#include "Student.h"
#include <iostream>
using namespace std;
void fun() {
Teacher teacher1; //無參構(gòu)造函數(shù),也可以Teacher teacher1 = Teacher();
Teacher teacher2(28, "kevin"); //有參構(gòu)造函數(shù),創(chuàng)建對象, 也可以Teacher teacher2 = Teacher(28, "kevin");
Teacher *p_teacher = new Teacher(29,"chenyu"); //對象指針,創(chuàng)建是需要new關(guān)鍵字
teacher1.setAge(31);
teacher1.setName("jason");
cout << "teacher1 name: " << teacher1.getName() << endl;
cout << "teacher1 age: " << teacher1.getAge() << endl;
cout << "teacher2 name: " << teacher2.getName() << endl;
cout << "teacher2 age: " << teacher2.getAge() << endl;
cout << "p_teacher name: " << p_teacher->getName() << endl;
cout << "p_teacher age: " << p_teacher->getAge() << endl;
//及時(shí)釋放
delete p_teacher;
p_teacher = nullptr;
}
void main() {
fun();
system("pause");
}
值傳遞&引用傳遞
在函數(shù)調(diào)用中,如果需要將類的對象作為形參,傳入到某個(gè)函數(shù)進(jìn)行調(diào)用,這種情況分為值傳遞和引用傳遞。
- 值傳遞
//為什么這里只調(diào)用了析構(gòu)函數(shù),沒有調(diào)用構(gòu)造函數(shù)?
//值傳遞 存在值拷貝
void funValuePass(Teacher teacher)
{
teacher.setAge(31);
teacher.setName("liuyan");
cout << "funValuePass teacher name: " << teacher.getName() << endl;
cout << "funValuePass teacher age: " << teacher.getAge() << endl;
}
-
引用傳遞
什么是引用?
引用是原變量的一個(gè)別名.
n 相當(dāng)于m 的別名(綽號(hào)),對n 的任何操作就是對m 的操作。例如有個(gè)人叫是JackMa,綽號(hào)是“馬爸爸”。說“馬爸爸”怎么怎么的,其實(shí)就是在說JackMa。所以n 既不是m 的拷貝,也不是指向m 的指針,其實(shí)n就是m 它自己。
c++中的引用 (就是再堆中分配空間)

堆(heap)空間:
動(dòng)態(tài)分配的內(nèi)存(malloc 等api 分配在堆空間, c++中的new)
堆用于存放進(jìn)程運(yùn)行時(shí)動(dòng)態(tài)分配的內(nèi)存段,可動(dòng)態(tài)擴(kuò)張或縮減。堆中內(nèi)容是匿名的,不能按名字直接訪問,只能通過指針間接訪問。
棧(stack)空間:
局部變量、函數(shù)參數(shù)、返回地址等(系統(tǒng)自動(dòng)分配的臨時(shí)內(nèi)存)Linux有專門的寄存器管理?xiàng)?nèi)存(效率高)
.bss段
未初始化或初值為0的全局變量和靜態(tài)局部變量
.data段
已初始化且初值非0的全局變量和靜態(tài)局部變量
.text段
可執(zhí)行代碼、只讀變量,全局靜態(tài)變量
//引用傳遞
//c++ 引用 是內(nèi)存空間的別名 不存在拷貝 只傳遞內(nèi)存別名
void funRefPass(Teacher &teacher) {
teacher.setAge(32);
teacher.setName("Chen");
cout << "funRefPass teacher name: " << teacher.getName() << endl;
cout << "funRefPass teacher age: " << teacher.getAge() << endl;
}
- 引用和指針的區(qū)別
- 指針是一個(gè)實(shí)體,而引用僅是個(gè)別名;
- 引用使用時(shí)無需解引用(*),指針需要解引用;
- 引用只能在定義時(shí)被初始化一次,之后不可變;指針可變; 引用“從一而終” 。
- 引用沒有 const,指針有 const,const 的指針不可變;
- 引用不能為空,指針可以為空;
- “sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或?qū)ο蟮牡刂罚┑拇笮。?/li>
- 引用是面向?qū)ο蟮母拍?,指針是面向過程種的概念,C++能夠混編C語言,所以C++支持指針
- 代碼調(diào)用
值引用:
void main() {
Teacher teacher;
teacher.setAge(24);
teacher.setName("lily");
//值傳遞
funValuePass(teacher);
//這邊值沒有發(fā)生變化
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
system("pause");
}
輸出結(jié)果:

引用傳遞:
void main() {
Teacher teacher;
teacher.setAge(24);
teacher.setName("lily");
//引用傳遞
funRefPass(teacher);
//這邊值已經(jīng)發(fā)生變化
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl; */
system("pause");
}
輸出結(jié)果:

拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),它在創(chuàng)建對象時(shí),是使用同一類中之前創(chuàng)建的對象來初始化新創(chuàng)建的對象。
拷貝構(gòu)造函數(shù)通常用于:
- 通過使用另一個(gè)同類型的對象來初始化新創(chuàng)建的對象。
- 復(fù)制對象把它作為參數(shù)傳遞給函數(shù)。
- 復(fù)制對象,并從函數(shù)返回這個(gè)對象。
對拷貝,C++ 的String源碼,最能體現(xiàn)。
舉個(gè)例子區(qū)分賦值和拷貝
String s1("aaa");
String s2("bbb");
String str = s1; //這個(gè)就是調(diào)用了拷貝構(gòu)造函數(shù),等同String str(s1);
str = s2 //這個(gè)是調(diào)用賦值函數(shù)
拷貝分為 淺拷貝和深拷貝
淺拷貝:位拷貝,拷貝構(gòu)造函數(shù),賦值重載,多個(gè)對象共用同一塊資源,同一塊資源釋放多次,崩潰或者內(nèi)存泄漏
深拷貝:每個(gè)對象共同擁有自己的資源,必須顯式提供拷貝構(gòu)造函數(shù)和賦值運(yùn)算符
- 淺拷貝
Student::Student(const Student &student) {
cout << " MyStudent 拷貝構(gòu)造函數(shù) 地址:" << this << endl;
this->age = student.age;
this->name = student.name;
this->teacherName = student.teacherName;
}
- 深拷貝
Student::Student(const Student &student) {
cout << " Student 深拷貝構(gòu)造函數(shù) 地址:" << this << endl;
int len = strlen(student.name);
this->name = (char *)malloc(len + 1);
strcpy(this->name, student.name);
len = strlen(student.teacherName);
this->teacherName = (char *)malloc(len + 1);
strcpy(this->teacherName, student.teacherName);
}
- 完整的例子
Student.h:
#pragma once
class Student
{
public:
Student(int age, char *name, char *teacherName);
~Student();
/*private:
//重寫默認(rèn)的拷貝構(gòu)造函數(shù) 這種方案不常用
MyStudent(const MyStudent &student);*/
Student::Student(const Student &student);
public:
int age;
char *name;
char *teacherName;
};
Student.cpp:
#include "Student.h"
#include <iostream>
using namespace std;
Student::Student(int age, char *name, char *teacherName)
{
cout << " Student 構(gòu)造函數(shù) 地址:" << this << endl;
int len = strlen(name);
this->name = (char *)malloc(len + 1);
strcpy(this->name, name);
len = strlen(teacherName);
this->teacherName = (char *)malloc(len + 1);
strcpy(this->teacherName, teacherName);
}
Student::~Student()
{
cout << " Student 析構(gòu)函數(shù) 地址:" << this << endl;
free(this->name); //拷貝構(gòu)造函數(shù)釋放野指針出錯(cuò)
free(this->teacherName);
}
//默認(rèn)拷貝構(gòu)造函數(shù) 實(shí)現(xiàn)淺拷貝
/*Student::Student(const Student &student) {
cout << " MyStudent 拷貝構(gòu)造函數(shù) 地址:" << this << endl;
this->age = student.age;
this->name = student.name;
this->teacherName = student.teacherName;
}*/
//覆蓋默認(rèn)的拷貝構(gòu)造函數(shù) 實(shí)現(xiàn)深拷貝
Student::Student(const Student &student) {
cout << " Student 深拷貝構(gòu)造函數(shù) 地址:" << this << endl;
int len = strlen(student.name);
this->name = (char *)malloc(len + 1);
strcpy(this->name, student.name);
len = strlen(student.teacherName);
this->teacherName = (char *)malloc(len + 1);
strcpy(this->teacherName, student.teacherName);
}
main.cpp:
// 1. 淺拷貝
// 2.避免淺拷貝引發(fā)野指針問題
// 2.1 深拷貝
// 2.2 私有化拷貝構(gòu)造函數(shù)
void copyTest() {
Student student = Student(21, "Jake", "Jhone");
cout << "setFunX student1 name: " << student.name << endl;
cout << "setFunX student1 age: " << student.age << endl;
cout << "setFunX student1 age: " << student.teacherName << endl;
Student st2 = student; // 這里也調(diào)用了拷貝構(gòu)造函數(shù)
cout << "setFunX student2 name: " << st2.name << endl;
cout << "setFunX student2 age: " << st2.age << endl;
cout << "setFunX student2 age: " << st2.teacherName << endl;
}
void main() {
copyTest();
system("pause");
}
繼承& 多態(tài)
繼承
當(dāng)創(chuàng)建一個(gè)類時(shí),您不需要重新編寫新的數(shù)據(jù)成員和成員函數(shù),只需指定新建的類繼承了一個(gè)已有的類的成員即可。這個(gè)已有的類稱為基類,新建的類稱為派生類。
C++ 繼承的繼承指的就是基類和派生類的關(guān)系。
- 代碼:
基類Plane.h
#pragma once
#include <string>
using namespace std;
class Plane
{
public:
Plane();
Plane(std::string name, int year);
~Plane();
void fly();
void land();
void printf();
protected:
std::string name;
int year;
};
基類Plane.cpp
#include "Plane.h"
#include <iostream>
using namespace std;
Plane::Plane() :name("灣流"), year(1991) {
cout << "Plane 無參構(gòu)造函數(shù)" << name << year << endl;
}
Plane::Plane(std::string name, int year) :name(name), year(year) {
cout << "Plane 構(gòu)造函數(shù)" << name << year << endl;
}
Plane::~Plane()
{
cout << "Plane 析構(gòu)函數(shù)" << endl;
}
void Plane::fly() {
cout << "Plane fly" << endl;
}
void Plane::land() {
cout << "Plane land" << endl;
}
void Plane::printf() {
cout << "Plane printf " << "name = " << name << " year = " << year << endl;
}
派生類Jet.h:
#include "Plane.h"
class Jet : public Plane
{
public:
Jet();
Jet(std::string name, int year);
~Jet();
void fly();
void land();
void test();
};
派生類Jet.cpp:
#include "Jet.h"
#include <iostream>
using namespace std;
Jet::Jet() {
cout << "Jet 無參構(gòu)造函數(shù)" << name << year << endl;
}
Jet::Jet(std::string name, int year) {
cout << "Jet 構(gòu)造函數(shù)" << name << year << endl;
}
Jet::~Jet() {
cout << "Jet 析構(gòu)函數(shù)" << endl;
}
//重寫
void Jet::fly() {
cout << "Jet fly" << endl;
}
void Jet::land() {
cout << "Jet land" << endl;
}
void Jet::test() {
}
調(diào)用類main.cpp:
//1. 先調(diào)用父類的構(gòu)造函數(shù)
//2.釋放時(shí)先調(diào)用子類的析構(gòu)函數(shù)
//子類沒有 就使用父類的方法
//子類有實(shí)現(xiàn),就是用子類的重寫
//父類型的引用 賦值子類型的對象 方法都是父類型中的方法
void funExtends() {
Jet jet;
//jet.fly();
//jet.Plane::fly();
Plane *pl = &jet;
pl->fly();
Plane &p2 = jet;
p2.fly();
}
void main() {
funExtends();
system("pause");
}
輸出結(jié)果:父類型的引用 賦值子類型的對象 方法都是父類型中的方法

輸出的結(jié)果,調(diào)用的還是父類的方法,不是子類的方法,上面的情況明顯不是我們想要的結(jié)果,怎么解決呢?
方法:使用虛函數(shù) 讓派生類類 重載父類方法
在Plane.h中,將fly和land兩個(gè)方法添加virtual進(jìn)行修飾
virtual void fly();
virtual void land();
再次輸出結(jié)果:

-
繼承類型
如下代碼:A繼承基類B的時(shí)候,帶著修飾符,繼承的修飾符有三種:public、protected、private。
class A : public B{};
我們幾乎不使用 protected 或 private 繼承,通常使用 public 繼承。當(dāng)使用不同類型的繼承時(shí),遵循以下幾個(gè)規(guī)則:
| 繼承類型 | 說明 |
|---|---|
| public | 當(dāng)一個(gè)類派生自公有基類時(shí),基類的公有成員也是派生類的公有成員,基類的保護(hù)成員也是派生類的保護(hù)成員,基類的私有成員不能直接被派生類訪問,但是可以通過調(diào)用基類的公有和保護(hù)成員來訪問。 |
| protected | 當(dāng)一個(gè)類派生自保護(hù)基類時(shí),基類的公有和保護(hù)成員將成為派生類的保護(hù)成員。 |
| private | 當(dāng)一個(gè)類派生自私有基類時(shí),基類的公有和保護(hù)成員將成為派生類的私有成員。 |
-
多繼承
多繼承即一個(gè)子類可以有多個(gè)父類,它繼承了多個(gè)父類的特性。類似一個(gè)人可以有多個(gè)師傅;
class A{};
class B{};
class C: public A, public B{};
多態(tài)
- 概念
多態(tài)按字面的意思就是多種形態(tài)。當(dāng)類之間存在層次結(jié)構(gòu),并且類之間是通過繼承關(guān)聯(lián)時(shí),就會(huì)用到多。C++ 多態(tài)意味著調(diào)用成員函數(shù)時(shí),會(huì)根據(jù)調(diào)用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)。
C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運(yùn)行時(shí)將會(huì)根據(jù)對象的實(shí)際類型來調(diào)用相應(yīng)的函數(shù)。如果對象類型是派生類,就調(diào)用派生類的函數(shù);如果對象類型是基類,就調(diào)用基類的函數(shù)。 - 實(shí)例解釋
以上面的plane類為例,jet繼承了Plane,是plane的派生類,在進(jìn)行創(chuàng)建一個(gè)Copter派生類 繼承Plane基類
Copter.h:
#include "Plane.h"
class Copter : public Plane
{
public:
Copter();
Copter(std::string name, int year);
~Copter();
void fly();
void land();
};
Copter.cpp:
#include "Copter.h"
#include <iostream>
using namespace std;
Copter::Copter() {
cout << "Copter 無參構(gòu)造函數(shù)" << name << year << endl;
}
Copter::Copter(std::string name, int year) {
cout << "Copter 構(gòu)造函數(shù)" << name << year << endl;
}
Copter::~Copter() {
cout << "Copter 析構(gòu)函數(shù)" << endl;
}
//重寫
void Copter::fly() {
cout << "Copter fly" << endl;
}
void Copter::land() {
cout << "Copter land" << endl;
}
調(diào)用
Plane *plane;
Jet jet("波音707", 1997);
Copter copter("絕影", 2005);
// 存儲(chǔ)Jet的地址
plane = &jet;
// 調(diào)用Jet的函數(shù) fly
plane->fly();
// 存儲(chǔ)copter的地址
plane = &copter;
// 調(diào)用Copter的函數(shù) fly
plane->fly();
編譯輸出結(jié)果:

分類
虛函數(shù) (c++多態(tài)的基礎(chǔ)) 增加程序的擴(kuò)展性
動(dòng)態(tài)多態(tài): 程序運(yùn)行過程中,覺得哪一個(gè)函數(shù)被調(diào)用
靜態(tài)多態(tài): 重載(函數(shù)名稱相同,參數(shù)不同,面向?qū)ο蟮奶匦?,c 中不行)發(fā)生動(dòng)態(tài)多態(tài)的條件:
- 繼承
- 父類的引用或者指針指向子類的對象
- 函數(shù)的重寫
重載(overload):在相同作用域內(nèi),函數(shù)名稱相同,參數(shù)或常量性(const)不同的相關(guān)函數(shù)稱為重載。重載函數(shù)之間的區(qū)分主要在參數(shù)和常量性(const)的不同上,若僅僅是返回值或修飾符 virtual,public/protected/private的不同不被視為重載函數(shù)(無法通過編譯)。不同參數(shù)是指參數(shù)的個(gè)數(shù)或類型不同,而類型不同是指各類型之間不能進(jìn)行隱身類型轉(zhuǎn)換或不多于一次的用戶自定義類型轉(zhuǎn)換(關(guān)于類型轉(zhuǎn)換,請參考前文:類型轉(zhuǎn)型(Type Casting))。當(dāng)調(diào)用發(fā)生時(shí),編譯器在進(jìn)行重載決議時(shí)根據(jù)調(diào)用所提供的參數(shù)來選擇最佳匹配的函數(shù)。
重寫(override):派生類重寫基類中同名同參數(shù)同返回值的函數(shù)(通常是虛函數(shù),這是推薦的做法)。同樣重寫的函數(shù)可以有不同的修飾符virtual,public/protected/private。
- 純虛函數(shù)(抽象類)
- 當(dāng)一個(gè)類具有一個(gè)純虛函數(shù),這個(gè)類就是抽象類
- 抽象類不能實(shí)例化對象
- 子類繼承抽象類,必須要實(shí)現(xiàn)純虛函數(shù),如果沒有,子類也是抽象類
關(guān)于虛函數(shù)和純虛函數(shù)的具體:https://www.runoob.com/w3cnote/cpp-virtual-functions.html
友元
- 概念
類的友元函數(shù)是定義在類外部,但有權(quán)訪問類的所有私有(private)成員和保護(hù)(protected)成員。盡管友元函數(shù)的原型有在類的定義中出現(xiàn)過,但是友元函數(shù)并不是成員函數(shù)。采用friend 關(guān)鍵字 表示友元。 - 友元的兩種表現(xiàn)形式
- 友元函數(shù)
- 友元類
- 實(shí)例
class Girl
{
public:
//友元函數(shù)不能使用this
friend void modify(Girl *girl, int age); //聲明的友元函數(shù)
friend class Boy; //聲明的友元類
//friend void Boy::introduce();
void tell();
private:
int age = 16;
string name = "大笑";
};
//girl class的函數(shù)實(shí)現(xiàn)
void Girl::tell() {
cout << "age == " << age << endl;
}
class Boy
{
public:
Boy(Girl girl) {
this->girl = girl;
}
~Boy() {
}
void changGirl() {
girl.age = 28;
girl.name = "vava";
}
//已經(jīng)聲明為友元函數(shù) 可以訪問和修改私有屬性s
void introduce() {
cout << "My Girl friend age : " << girl.age << "name = " << girl.name << endl;
}
public:
Girl girl;
};
//外部實(shí)現(xiàn)
void modify(Girl *girl, int age) {
girl->age = age;
}
void main() {
/*Girl *girl = new Girl();
modify(girl, 31);
girl->tell();
delete girl;*/
Girl girl;
Boy boy = Boy(girl);
boy.introduce();
boy.changGirl();
boy.girl.tell();
boy.introduce();
system("pause");
}
輸出的結(jié)果


模板
模板是泛型編程的基礎(chǔ),泛型編程即以一種獨(dú)立于任何特定類型的方式編寫代碼。
- 表現(xiàn)形式
- 模板函數(shù)
- 模板類
- 實(shí)例
模板函數(shù)
template <typename T>
void myswap(T& a, T& b) {
T tmp = 0;
tmp = a;
a = b;
b = tmp;
cout << "myswap T" << endl;
}
void main() {
int a = 999;
int b = 666;
myswap(a,b);
cout << "a = "<< a << "b = " <<b << endl;
char c = '9';
char v = '6';
myswap(c, v);
cout << "c = " << c << "v = " << v << endl;
輸出結(jié)果:

模板類
template<class T>
class A
{
public:
A(T a) {
this->a = a;
}
~A() {
}
protected:
T a;
};
template <class T>
class C : public A<T>
{
public:
C(T c, T a) : A<T>(a) {
this->c = c;
}
void tell() {
cout << "a : " << a << "c " << c << endl;
}
private:
T c;
};
void main() {
C<int> c(1,2);
c.tell();
}
輸出結(jié)果:

類型轉(zhuǎn)換
C++ 常見的幾種類型轉(zhuǎn)換
- static_cast 普通值類型轉(zhuǎn)換
- const_cast 去常量
- dynamic_cast 基類和派生類之間的轉(zhuǎn)換
- reinterpret_cast 不通用 不常用 函數(shù)指針的轉(zhuǎn)換 (一般在Void * 之間轉(zhuǎn))
前三種是通用,常用的,第四種屬于不通用,不常用
- 實(shí)例
void func(const char c[]) {
//c[1] = 'a';
//去掉const 關(guān)鍵字
char* c_p = const_cast<char *>(c);
c_p[1] = 'X';
}
class Person {
public:
virtual void print() {
cout << "人" << endl;
}
};
class Man : public Person
{
public:
void print() {
cout << "男人" << endl;
}
void chasing() {
cout << "泡妞" << endl;
}
};
class Woman :public Person
{
public:
void print() {
cout << "女人" << endl;
}
void createBaby() {
cout << "造小孩" << endl;
}
};
void funx(Person* obj) {
//Man *m = (Man *)obj;
//m->chasing();
Man *m = dynamic_cast<Man*>(obj);
if (m != nullptr) {
m->chasing();
}
else {
cout << "還需要去趟泰國" << endl;
}
}
void main() {
int i = 8;
double d = 9.5;
//i = (int)d;
i = static_cast<int> (d);
char c[] = "hello";
cout << "c = " << c << endl;
func(c);
cout << "c = " << c << endl;
Man *m = new Man();
funx(m);
system("pause");
}
異常捕獲
異常是程序在執(zhí)行期間產(chǎn)生的問題;
異常提供了一種轉(zhuǎn)移程序控制權(quán)的方式。C++ 異常處理涉及到三個(gè)關(guān)鍵字:try、catch、throw。 類Java的異常。
- throw: 當(dāng)問題出現(xiàn)時(shí),程序會(huì)拋出一個(gè)異常。這是通過使用 throw 關(guān)鍵字來完成的。
- catch: 在您想要處理問題的地方,通過異常處理程序捕獲異常。catch 關(guān)鍵字用于捕獲異常。
- try: try 塊中的代碼標(biāo)識(shí)將被激活的特定異常。它后面通常跟著一個(gè)或多個(gè) catch 塊。
- 實(shí)例
void main() {
try
{
int age = 300;
if (age > 200) {
throw "xxx";
}
}
catch (int a)
{
cout << "int 異常"<<endl;
}
catch (char * b) {
cout << "char b" <<b << endl;
}
system("pause");
}
輸出結(jié)果:

- 定義新的異常
class NullPointerException : public exception {
public:
NullPointerException(char * msg) :exception(msg) {
}
};
void main() {
try
{
int age = 300;
if (age > 200) {
throw NullPointerException("pgone");
}
}
catch (int a)
{
cout << "int 異常" << endl;
}
catch (char * b) {
cout << "char b" << b << endl;
}
catch (NullPointerException msg) {
}
system("pause");
}
筆記就做到這了。如果有什么問題歡迎指出。
參考文獻(xiàn)
https://www.runoob.com/w3cnote/cpp-virtual-functions.html
https://blog.csdn.net/qq_39477053/article/details/80322260
https://blog.csdn.net/BLUCEJIE/article/details/104474930