前言
最近項(xiàng)目在開發(fā)涉及到的C++內(nèi)容相對比較多凉倚,整理一下卦睹,過程中用到的C++面向?qū)ο蟮恼Z法筆記
正文
知識點(diǎn)的概要
- C++ 類 & 對象
- 值傳遞&引用傳遞
- 拷貝構(gòu)造函數(shù)
- 繼承& 多態(tài)
- 友元
- 模板
- 類型轉(zhuǎn)換
- 異常捕獲
類& 對象
-
C++類定義:本質(zhì)上是定義一個數(shù)據(jù)類型的合集
類定義是以關(guān)鍵字 class 開頭疗我,后跟類的名稱袖迎。類的主體是包含在一對花括號;
class Teacher
{
public:
Teacher(); //構(gòu)造函數(shù) (malloc)
Teacher(int age, char * name); //構(gòu)造函數(shù) (malloc)
~Teacher(); //析構(gòu)函數(shù) 釋放在構(gòu)造函數(shù)里面動態(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ù)里面動態(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;
//及時釋放
delete p_teacher;
p_teacher = nullptr;
}
void main() {
fun();
system("pause");
}
值傳遞&引用傳遞
在函數(shù)調(diào)用中漩绵,如果需要將類的對象作為形參,傳入到某個函數(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;
}
-
引用傳遞
什么是引用祟印?
引用是原變量的一個別名.
n 相當(dāng)于m 的別名(綽號),對n 的任何操作就是對m 的操作粟害。例如有個人叫是JackMa蕴忆,綽號是“馬爸爸”。說“馬爸爸”怎么怎么的悲幅,其實(shí)就是在說JackMa套鹅。所以n 既不是m 的拷貝,也不是指向m 的指針汰具,其實(shí)n就是m 它自己卓鹿。
c++中的引用 (就是再堆中分配空間)
堆(heap)空間:
動態(tài)分配的內(nèi)存(malloc 等api 分配在堆空間, c++中的new)
堆用于存放進(jìn)程運(yùn)行時動態(tài)分配的內(nèi)存段,可動態(tài)擴(kuò)張或縮減留荔。堆中內(nèi)容是匿名的吟孙,不能按名字直接訪問,只能通過指針間接訪問聚蝶。
棧(stack)空間:
局部變量杰妓、函數(shù)參數(shù)、返回地址等(系統(tǒng)自動分配的臨時內(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ū)別
- 指針是一個實(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)建對象時,是使用同一類中之前創(chuàng)建的對象來初始化新創(chuàng)建的對象裳瘪。
拷貝構(gòu)造函數(shù)通常用于:
- 通過使用另一個同類型的對象來初始化新創(chuàng)建的對象土浸。
- 復(fù)制對象把它作為參數(shù)傳遞給函數(shù)。
- 復(fù)制對象彭羹,并從函數(shù)返回這個對象黄伊。
對拷貝,C++ 的String源碼派殷,最能體現(xiàn)还最。
舉個例子區(qū)分賦值和拷貝
String s1("aaa");
String s2("bbb");
String str = s1; //這個就是調(diào)用了拷貝構(gòu)造函數(shù),等同String str(s1);
str = s2 //這個是調(diào)用賦值函數(shù)
拷貝分為 淺拷貝
和深拷貝
淺拷貝:位拷貝毡惜,拷貝構(gòu)造函數(shù)拓轻,賦值重載,多個對象共用同一塊資源经伙,同一塊資源釋放多次扶叉,崩潰或者內(nèi)存泄漏
深拷貝:每個對象共同擁有自己的資源,必須顯式提供拷貝構(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ù)釋放野指針出錯
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)建一個類時帕膜,您不需要重新編寫新的數(shù)據(jù)成員和成員函數(shù)枣氧,只需指定新建的類繼承了一個已有的類的成員即可。這個已有的類稱為基類泳叠,新建的類稱為派生類作瞄。
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.釋放時先調(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兩個方法添加virtual進(jìn)行修飾
virtual void fly();
virtual void land();
再次輸出結(jié)果:
-
繼承類型
如下代碼:A繼承基類B的時候搪桂,帶著修飾符,繼承的修飾符有三種:public、protected踢械、private酗电。
class A : public B{};
我們幾乎不使用 protected 或 private 繼承,通常使用 public 繼承内列。當(dāng)使用不同類型的繼承時撵术,遵循以下幾個規(guī)則:
繼承類型 | 說明 |
---|---|
public | 當(dāng)一個類派生自公有基類時,基類的公有成員也是派生類的公有成員话瞧,基類的保護(hù)成員也是派生類的保護(hù)成員嫩与,基類的私有成員不能直接被派生類訪問,但是可以通過調(diào)用基類的公有和保護(hù)成員來訪問交排。 |
protected | 當(dāng)一個類派生自保護(hù)基類時划滋,基類的公有和保護(hù)成員將成為派生類的保護(hù)成員。 |
private | 當(dāng)一個類派生自私有基類時埃篓,基類的公有和保護(hù)成員將成為派生類的私有成員处坪。 |
-
多繼承
多繼承即一個子類可以有多個父類,它繼承了多個父類的特性架专。類似一個人可以有多個師傅稻薇;
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)時睛低,就會用到多案狠。C++ 多態(tài)意味著調(diào)用成員函數(shù)時,會根據(jù)調(diào)用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)钱雷。
C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字骂铁,在派生類中重寫該函數(shù),運(yùn)行時將會根據(jù)對象的實(shí)際類型來調(diào)用相應(yīng)的函數(shù)罩抗。如果對象類型是派生類拉庵,就調(diào)用派生類的函數(shù);如果對象類型是基類套蒂,就調(diào)用基類的函數(shù)钞支。 - 實(shí)例解釋
以上面的plane類為例,jet繼承了Plane操刀,是plane的派生類烁挟,在進(jìn)行創(chuàng)建一個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);
// 存儲Jet的地址
plane = &jet;
// 調(diào)用Jet的函數(shù) fly
plane->fly();
// 存儲copter的地址
plane = &copter;
// 調(diào)用Copter的函數(shù) fly
plane->fly();
編譯輸出結(jié)果:
分類
虛函數(shù) (c++多態(tài)的基礎(chǔ)) 增加程序的擴(kuò)展性
動態(tài)多態(tài): 程序運(yùn)行過程中,覺得哪一個函數(shù)被調(diào)用
靜態(tài)多態(tài): 重載(函數(shù)名稱相同骨坑,參數(shù)不同撼嗓,面向?qū)ο蟮奶匦В琧 中不行)發(fā)生動態(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ù)的個數(shù)或類型不同,而類型不同是指各類型之間不能進(jìn)行隱身類型轉(zhuǎn)換或不多于一次的用戶自定義類型轉(zhuǎn)換(關(guān)于類型轉(zhuǎn)換押搪,請參考前文:類型轉(zhuǎn)型(Type Casting))。當(dāng)調(diào)用發(fā)生時浅碾,編譯器在進(jìn)行重載決議時根據(jù)調(diào)用所提供的參數(shù)來選擇最佳匹配的函數(shù)大州。
重寫(override):派生類重寫基類中同名同參數(shù)同返回值的函數(shù)(通常是虛函數(shù),這是推薦的做法)垂谢。同樣重寫的函數(shù)可以有不同的修飾符virtual厦画,public/protected/private。
- 純虛函數(shù)(抽象類)
- 當(dāng)一個類具有一個純虛函數(shù)滥朱,這個類就是抽象類
- 抽象類不能實(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++ 異常處理涉及到三個關(guān)鍵字:try麦乞、catch蕴茴、throw。 類Java的異常姐直。
- throw: 當(dāng)問題出現(xiàn)時荐开,程序會拋出一個異常。這是通過使用 throw 關(guān)鍵字來完成的简肴。
- catch: 在您想要處理問題的地方晃听,通過異常處理程序捕獲異常。catch 關(guān)鍵字用于捕獲異常。
- try: try 塊中的代碼標(biāo)識將被激活的特定異常能扒。它后面通常跟著一個或多個 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