前言
最近發現要學習C++來開發NDK,不得不把基礎的東西記錄下來,否則學的太多會混淆,廢話不多說,開始記錄我的C++學習之旅吧
HelloWord
- 導庫
- 命名空間
- 輸出函數
#include <iostream>
//必須帶有命名空間才能使用cout等
using namespace std;
int main()
{
cout << "Hello, world!" << endl;
return ;
}
命名空間
1、命名空間屬性通路和結構體通路
namespace NSP_A{
int a = ;
struct Student{
char name[];
int age;
};
}
void main(){
//使用命名空間
cout << NSP_A::a << endl;
//使用命名空間中的結構體
using NSP_A::Student;
Student t;
}
2、命名空間的嵌套
namespace NSP_B{
//命名空間嵌套
namespace NSP_C{
int c = ;
}
}
void main(){
cout << NSP_B::NSP_C::c << endl;
}
類
1、類、屬性、方法的聲明與使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <iostream>
#include <stdarg.h>
using namespace std;
#define PI 3.14
class MyCircle{
//屬性(共用權限通路修飾符)
private:
double r;
double s;
public:
void setR(double r){
this->r = r;
}
//擷取面積
double getS(){
return PI * r * r;
}
};
void main(){
MyCircle c;
c.setR();
cout << "圓的面積:" << c.getS() << endl;
system("pause");
}
2、類的大小
類的大小隻計算普通屬性的大小,其他都不包括在内
class A{
public:
int i;
int j;
int k;
static int m;
};
class B{
public:
int i;
int j;
int k;
void myprintf(){
cout << "列印" << endl;
}
};
void main(){
//輸出的結果都是12
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
}
繼承
1、繼承基本使用
class Human{
public:
void say(){
cout << "說話" << endl;
}
protected:
int age;
};
class Man : public Human{
};
void main(){
//子類
Man m1;
m1.say();
//将子類指派給父類的引用或指針
Human* h_p = &m1;
h_p->say();
Human &h1 = m1;
h1.say();
//子類對象初始化父類類型的對象
Human h2 = m1;
h2.say();
//子類對象調用父類的成員
m1.Human::say();
m1.Human::age = ;
}
2、向父類構造方法傳參
class Human{
public:
Human(char* name, int age){
this->name = name;
this->age = age;
}
protected:
char* name;
int age;
};
class Man : public Human{
public:
//給父類構造函數傳參,同時給屬性h對象指派
Man(char *brother, char *s_name, int s_age, char *h_name, int h_age) : Human(s_name, s_age), h(h_name,h_age){
this->brother = brother;
}
private:
Human h;
};
void main(){
Man m1("Hensen","HensenBoy",,"HensenGirl",);
}
3、多繼承的實作
class Person{
};
class Citizen{
};
class Student : public Person, public Citizen{
};
4、繼承間的通路修飾符
基類中 繼承方式 子類中
public & public繼承 = > public
public & protected繼承 = > protected
public & private繼承 = > private
protected & public繼承 = > protected
protected & protected繼承 = > protected
protected & private繼承 = > private
private & public繼承 = > 子類無權通路
private & protected繼承 = > 子類無權通路
private & private繼承 = > 子類無權通路
5、繼承的二義性
virtual:表示虛繼承,不同路徑繼承來的同名成員隻有一份拷貝,解決不明确的問題
class A{
public:
char* name;
};
//這裡面加了virtual關鍵字
class A1 : virtual public A{
};
//這裡面加了virtual關鍵字
class A2 : virtual public A{
};
class B : public A1, public A2{
};
void main(){
B b;
//如果程式不加virtual關鍵字就會導緻二義性,系統無法辨識哪個類的name屬性,會報錯
b.name = "Hensen";
//這裡通過指定父類顯示調用是可以的
b.A1::name = "Hensen";
b.A2::name = "Hensen";
}
多态
1、多态的基本使用
//Plane.h檔案
#pragma once
//普通飛機
class Plane{
public:
virtual void fly();
virtual void land();
};
//Plane.cpp檔案
#include "Plane.h"
#include <iostream>
using namespace std;
void Plane::fly(){
cout << "起飛" << endl;
}
void Plane::land(){
cout << "着陸" << endl;
}
//Jet.h檔案
#pragma once
#include "Plane.h"
//直升飛機
class Jet : public Plane{
virtual void fly();
virtual void land();
};
//Jet.cpp檔案
#include "Jet.h"
#include <iostream>
using namespace std;
void Jet::fly(){
cout << "直升飛機在原地起飛..." << endl;
}
void Jet::land(){
cout << "直升飛機降落在女神的屋頂..." << endl;
}
#include "Plane.h"
#include "Jet.h"
#include "Copter.h"
//業務函數
void bizPlay(Plane& p){
p.fly();
p.land();
}
void main(){
Plane p1;
bizPlay(p1);
//直升飛機
Jet p2;
bizPlay(p2);
}
引用
1、引用的使用
void main(){
int a = ;
//&是C++中的引用,引用:變量的另外一個别名,共用同個位址
int &b = a;
cout << b << endl;
}
2、引用與指針的差別
- 不存在空引用,引用必須連接配接到一塊合法的記憶體。
- 一旦引用被初始化為一個對象,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象。
- 引用必須在建立時被初始化。指針可以在任何時間被初始化。
3、引用與指針寫法上的差異
struct Teacher{
char* name;
int age;
};
//帶有結構體指針的寫法
void myprint(Teacher *t){
cout << t->name << "," << t->age << endl;
//(*t).name
}
//帶有結構體引用的寫法
void myprint2(Teacher &t){
cout << t.name << "," << t.age << endl;
t.age = ;
}
//指針值交換
void swap_1(int *a, int *b){
int c = ;
c = *a;
*a = *b;
*b = c;
}
//引用值交換
void swap_2(int &a, int &b){
int c = ;
c = a;
a = b;
b = c;
}
void main(){
Teacher t;
t.name = "Hensen";
t.age = ;
//指針的寫法
myprint(&t);
//引用的寫法
myprint2(t);
int x = ;
int y = ;
//指針的寫法
swap_1(&x, &y);
//引用的寫法
swap_2(x,y);
}
4、引用的作用
- 把引用作為參數:C++支援把引用作為參數傳給函數,這比傳一般的參數更安全
- 把引用作為傳回值:可以從C++函數中傳回引用,就像傳回其他資料類型一樣
5、指針引用,代替二級指針
struct Teacher{
char* name;
int age;
};
//引用的寫法
void getTeacher(Teacher* &p){
p = (Teacher*)malloc(sizeof(Teacher));
p->age = ;
}
//二級指針的寫法,原本應該這樣寫,但是已經被引用的寫法代替了
void getTeacher(Teacher **p){
Teacher *tmp = (Teacher*)malloc(sizeof(Teacher));
tmp->age = ;
*p = tmp;
}
void main(){
Teacher *t = NULL;
//傳遞引用的指針t,相當于二級指針
getTeacher(&t);
}
6、常引用,類似于java中final
//常引用在方法中的引用
void myprint(const int &a){
cout << a << endl;
}
void main(){
//引用必須要有值,不能為空,下面寫法是錯誤的
//const int a;
//int &a = NULL;
//常引用屬性使用一
int a = , b = ;
const int &c = a;
//常引用屬性使用二
const int &d = ;
}
7、引用與指針的大小
struct Teacher{
char name[];
int age;
};
void main(){
Teacher t;
//引用
Teacher &t1 = t;
//指針
Teacher *p = &t;
//結果是24,引用相當于變量的别名
cout << sizeof(t1) << endl;
//結果是4,指針隻是存放的位址
cout << sizeof(p) << endl;
system("pause");
}
異常
1、C++異常處理,會根據抛出的異常資料類型,進入到相應的catch塊中
void main(){
try{
int age = ;
if (age > ){
throw ;
}
}
catch (int a){
cout << "int異常" << endl;
}
catch (char* b){
cout << b << endl;
}
catch (...){
cout << "未知異常" << endl;
}
}
2、向下抛出異常
void mydiv(int a, int b){
if (b == ){
throw "除數為零";
}
}
void func(){
try{
mydiv(, );
}
catch (char* a){
throw a;
}
}
void main(){
try{
func();
}
catch (char* a){
cout << a << endl;
}
}
3、抛出對象
class MyException{
};
void mydiv(int a, int b){
if (b == ){
throw MyException();
//不要抛出異常指針
//throw new MyException;
}
}
void main(){
try{
mydiv(,);
}
catch (MyException& e2){
cout << "MyException引用" << endl;
}
catch (MyException* e1){
cout << "MyException指針" << endl;
//指針的話需要手動釋放記憶體
delete e1;
}
}
4、方法抛出異常
void mydiv(int a, int b) throw (char*, int) {
if (b == ){
throw "除數為零";
}
}
5、标準異常
//需要導入标準異常的依賴庫
#include<stdexcept>
class NullPointerException : public exception{
public:
NullPointerException(char* msg) : exception(msg){
}
};
void mydiv(int a, int b){
if (b > ){
throw out_of_range("超出範圍");
}
else if (b == NULL){
throw NullPointerException("為空");
}
else if (b == ){
throw invalid_argument("參數不合法");
}
}
void main(){
try{
mydiv(,NULL);
}
catch (out_of_range e1){
cout << e1.what() << endl;
}
catch (NullPointerException& e2){
cout << e2.what() << endl;
}
catch (...){
cout << "未知異常" << endl;
}
}
6、外部類異常
class Err{
public:
class MyException{
public:MyException(){
}
};
};
void mydiv(int a, int b){
if (b > ){
throw Err::MyException();
}
}
IO流
1、普通檔案
#include <iostream>
#include <fstream>
void main(){
char* fname = "c://dest.txt";
//輸出流
ofstream fout(fname);
//建立失敗
if (fout.bad()){
return;
}
//寫入檔案
fout << "Hensen" << endl;
//關閉輸出流
fout.close();
//輸入流
ifstream fin(fname);
//建立失敗
if (fin.bad()){
return;
}
char ch;
//讀取資料
while (fin.get(ch)){
cout << ch;
}
//關閉輸入流
fin.close();
}
2、二進制檔案
void main(){
char* src = "c://src.jpg";
char* dest = "c://dest.jpg";
//輸入流
ifstream fin(src, ios::binary);
//輸出流
ofstream fout(dest, ios::binary);
if (fin.bad() || fout.bad()){
return;
}
while (!fin.eof()){
//讀取
char buff[] = {};
fin.read(buff,);
//寫入
fout.write(buff,);
}
//關閉
fin.close();
fout.close();
}
3、C++對象的持久化
class Person
{
public:
Person()
{
}
Person(char * name, int age)
{
this->name = name;
this->age = age;
}
void print()
{
cout << name << "," << age << endl;
}
private:
char * name;
int age;
};
void main()
{
Person p1("Hensen", );
Person p2("HensenBoy", );
//輸出流
ofstream fout("c://c_obj.data", ios::binary);
fout.write((char*)(&p1), sizeof(Person));
fout.write((char*)(&p2), sizeof(Person));
fout.close();
//輸入流
ifstream fin("c://c_obj.data", ios::binary);
Person tmp;
fin.read((char*)(&tmp), sizeof(Person));
tmp.print();
fin.read((char*)(&tmp), sizeof(Person));
tmp.print();
}
函數
1、函數的重載
函數可以傳預設值參數,如果調用存在參數,則預設參數會被替代
void myprint(int x, int y = , int z = ){
cout << x << endl;
}
//重載
void myprint(int x,bool ret){
cout << x << endl;
}
void main(){
myprint();
//覆寫預設參數的9和8
myprint(,,);
}
2、可變參數函數
void func(int i,...)
{
//可變參數指針
va_list args_p;
//可變參數設定開始位置
//i表示可變參數的前一位參數,從i開始,後面的就是可變參數
va_start(args_p,i);
int a = va_arg(args_p,int);
char b = va_arg(args_p, char);
int c = va_arg(args_p, int);
cout << a << endl;
cout << b << endl;
cout << c << endl;
//可變參數設定結束
va_end(args_p);
}
void main(){
//使用
func(,,'b',);
}
可變參數也可以循環讀取,但是必須保證所有數大于0使用
void func(int i,...)
{
va_list args_p;
//開始
va_start(args_p,i);
int value;
while (){
value = va_arg(args_p,int);
if (value <= ){
break;
}
cout << value << endl;
}
//結束
va_end(args_p);
}
3、靜态屬性和方法
class Teacher{
public:
char* name;
//計數器
static int total;
public:
Teacher(char* name){
this->name = name;
cout << "Teacher有參構造函數" << endl;
}
void setName(char* name){
this->name = name;
}
char* getName(){
return this->name;
}
//計數,靜态函數
static void count(){
total++;
cout << total << endl;
}
};
//靜态屬性初始化指派
int Teacher::total = ;
void main(){
//靜态變量的使用
Teacher::total++;
cout << Teacher::total << endl;
//靜态方法的使用一
Teacher::count();
//靜态方法的使用二
Teacher t1("Hensen");
t1.count();
}
4、常量對象和常函數
class Teacher{
private:
char* name;
int age;
public:
Teacher(char* name,int age){
this->name = name;
this->age = age;
cout << "Teacher有參構造函數" << endl;
}
//常函數,目前對象不能被修改,防止資料成員被非法通路
void myprint() const{
//不能通過this->name修改值
cout << this->name << "," << this->age << endl;
}
void myprint2(){
cout << this->name << "," << this->age << endl;
}
};
void main(){
//普通對象
Teacher t1("Hensen",);
//常對象
const Teacher t2("rose", );
//普通對象可以調用常函數,也可以調用普通函數
t1.myprint();
//t2.myprint2(); 常量對象隻能調用常量函數,不能調用非常量函數
t2.myprint();
}
虛函數
1、純虛函數(類似于抽象類)
- 當一個類具有一個純虛函數,這個類就是抽象類
- 抽象類不能執行個體化對象
- 子類繼承抽象類,必須要實作純虛函數,如果沒有,子類也是抽象類
class Shape{
public:
//純虛函數
virtual void sayArea() = ;
void print(){
cout << "hi" << endl;
}
};
class Circle : public Shape{
public:
Circle(int r){
this->r = r;
}
//必須實作純虛函數
void sayArea(){
cout << "圓的面積:" << ( * r * r) << endl;
}
private:
int r;
};
void main(){
Circle c();
}
2、接口
//接口(隻是邏輯上的劃分,文法上跟抽象類的寫法沒有差別)
class Drawble{
virtual void draw();
};
模闆函數
1、模闆函數使用,相當于泛型
void myswap(int& a,int& b){
int tmp = ;
tmp = a;
a = b;
b = tmp;
}
void myswap(char& a, char& b){
char tmp = ;
tmp = a;
a = b;
b = tmp;
}
//可以将上面的函數抽取成模闆函數
template <typename T>
void myswap(T& a, T& b){
T tmp = ;
tmp = a;
a = b;
b = tmp;
}
void main(){
int a = , b = ;
//使用時,根據實際類型,指定模闆類型
myswap<int>(a,b);
}
模闆類
1、模闆類使用
template<class T>
class A{
public:
A(T a){
this->a = a;
}
protected:
T a;
};
void main(){
//執行個體化模闆類對象
A<int> a();
}
2、普通類繼承模闆類
class B : public A<int>{
public:
B(int a,int b) : A<int>(a){
this->b = b;
}
private:
int b;
};
3、模闆類繼承模闆類
template <class T>
class C : public A<T>{
public:
C(T c, T a) : A<T>(a){
this->c = c;
}
protected:
T c;
};
構造函數
函數分為三種
- 構造函數
- 析構函數
- 拷貝函數
1、無參構造函數和有參構造函數
class Teacher{
private:
char *name;
int age;
public:
//無參構造函數(無參構造函數會覆寫預設的無參構造函數)
Teacher(){
cout << "無參構造函數" << endl;
}
//有參構造函數會覆寫預設的構造函數
Teacher(char *name, int age){
this->name = name;
this->age = age;
cout << "有參構造函數" << endl;
}
};
void main(){
Teacher t1("Hensen",);
//另外一種調用方式
Teacher t2 = Teacher("Hensen",);
}
2、析構函數
class Teacher{
private:
char *name;
int age;
public:
//無參構造函數賦預設值
Teacher(){
this->name = (char*)malloc();
strcpy(name,"Hensen");
age = ;
cout << "無參構造函數" << endl;
}
//析構函數寫法
//當對象要被系統釋放時,析構函數被調用,一般使用于程式的善後工作
~Teacher(){
cout << "析構" << endl;
//釋放記憶體
free(this->name);
}
};
void func(){
Teacher t1;
}
void main(){
func();
}
3、拷貝構造函數
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
this->name = name;
this->age = age;
cout << "有參構造函數" << endl;
}
//拷貝構造函數寫法
//預設拷貝構造函數,就是值拷貝
Teacher(const Teacher &obj){
this->name = obj.name;
this->age = obj.age;
cout << "拷貝構造函數" << endl;
}
void myprint(){
cout << name << "," << age << endl;
}
};
Teacher func1(Teacher t){
t.myprint();
return t;
}
void main(){
Teacher t1("rose",);
func1(t1);
//這裡不會調用拷貝函數的
//Teacher t1 ;
//Teacher t2;
//t1 = t2;
}
拷貝構造函數被調用的場景:
- 聲明時指派:Teacher t2 = t1;
- 作為參數傳入,實參給形參指派:上面的寫法就是
- 作為函數傳回值傳回,給變量初始化指派:Teacher t3 = func1(t1);
4、拷貝函數的問題,淺拷貝(值拷貝)問題
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
this->name = (char*)malloc();
strcpy(this->name,name);
this->age = age;
cout << "有參構造函數" << endl;
}
~Teacher(){
cout << "析構" << endl;
//釋放記憶體
free(this->name);
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
Teacher t1("rose", );
Teacher t2 = t1;
}
void main(){
func();
}
這樣的使用,會導緻t1和t2都調用析構函數,導緻同一份記憶體被釋放兩次,結果程式會報錯
5、解決淺拷貝問題,使用深拷貝
深拷貝很好了解,其實就是将參數進行再一次配置設定記憶體,這樣的程式就不會出錯
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
int len = strlen(name);
this->name = (char*)malloc(len+);
strcpy(this->name, name);
this->age = age;
cout << "有參構造函數" << endl;
}
~Teacher(){
cout << "析構" << endl;
//釋放記憶體
free(this->name);
}
//深拷貝
Teacher(const Teacher &obj){
int len = strlen(obj.name);
this->name = (char*)malloc(len+);
strcpy(this->name,obj.name);
this->age = obj.age;
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
Teacher t1("rose", );
Teacher t2 = t1;
}
void main(){
func();
}
6、構造函數初始化屬性寫法
class Student{
private:
int id;
//屬性對象可以直接的初始化
//Teacher t = Teacher("miss cang");
Teacher t1;
Teacher t2;
public:
//屬性對象可以在這裡間接的初始化
Student(int id,char *t1_n, char* t2_n) : t1(t1_n), t2(t2_n){
this->id = id;
cout << "Student有參構造函數" << endl;
}
void myprint(){
cout << id << "," << t1.getName() <<"," << t2.getName() << endl;
}
~Student(){
cout << "Student析構函數" << endl;
}
};
void func(){
Student s1(, "miss xu", "mrs li");
Student s2(, "miss ya", "mrs wang");
}
void main(){
func();
}
7、析構函數和構造函數的執行順序
class Human{
public:
Human(char* name, int age){
this->name = name;
this->age = age;
cout << "Human 構造函數" << endl;
}
~Human(){
cout << "Human 析構函數" << endl;
}
protected:
char* name;
int age;
};
class Man : public Human{
public:
//給父類構造函數傳參,同時給屬性對象指派
Man(char *brother, char *s_name, int s_age) : Human(s_name, s_age){
this->brother = brother;
cout << "Man 構造函數" << endl;
}
~Man(){
cout << "Man 析構函數" << endl;
}
private:
char* brother;
};
void func(){
Man m1("Hensen", "HensenBoy", );
}
void main(){
func();
}
輸出結果是:父類構造函數先調用,子類的析構函數先調用
Human構造函數
Man構造函數
Man析構函數
Human析構函數
友元函數
友元函數:使得類的私有屬性可以通過友元函數進行通路
1、友元函數
class A{
//友元函數聲明
friend void modify_i(A *p, int a);
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
//友元函數的實作
void modify_i(A *p, int a){
p->i = a;
}
void main(){
A* a = new A();
a->myprint();
modify_i(a,);
a->myprint();
}
2、友元類
class A{
//友元類聲明,表示B這個友元類可以通路A類的任何成員
friend class B;
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
class B{
private:
A a;
public:
void accessAny(){
a.i = ;
}
};
類型轉換
C++類型轉換分為4種
- static_cast:類型轉換,意圖明顯,增加可閱讀性
- const_cast:常量的轉換,将常量取出,并可以對常量進行修改
- dynamic_cast:子類類型轉為父類類型
- reinterpret_cast:函數指針轉型,不具備移植性
1、static_cast的使用
void* func(int type){
switch (type){
case : {
int i = ;
return &i;
}
case : {
int a = 'X';
return &a;
}
default:{
return NULL;
}
}
}
void func2(char* c_p){
cout << *c_p << endl;
}
void main(){
int i = ;
double d = ;
i = static_cast<int>(d);
//C的寫法
//char* c_p = (char*)func(2);
//C++的寫法
char* c_p = static_cast<char*>(func());
//C的寫法
//func2((char*)(func(2)));
//C++的寫法
func2(static_cast<char*>(func()));
}
2、const_cast的使用
void func(const char c[]){
//C的寫法
//char* c_p = (char*)c;
//c_p[1] = 'X';
//C++的寫法,提高了可讀性
char* c_p = const_cast<char*>(c);
c_p[] = 'Y';
cout << c << endl;
}
void main(){
char c[] = "hello";
func(c);
}
3、dynamic_cast的使用
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 carebaby(){
cout << "生孩子" << endl;
}
};
void func(Person* obj){
//C的寫法,C隻會調用傳遞過來的對象方法,并不知道轉型失敗這回事
//Man* m = (Man*)obj;
//m->print();
//C++的寫法,dynamic_cast如果轉型失敗,會傳回NULL,保證了代碼的安全性
Man* m = dynamic_cast<Man*>(obj);
if (m != NULL){
m->chasing();
}
Woman* w = dynamic_cast<Woman*>(obj);
if (w != NULL){
w->carebaby();
}
}
void main(){
Woman w1;
Person *p1 = &w1;
//輸出結果是生孩子
func(p1);
}
4、reinterpret_cast的使用
void func1(){
cout << "func1" << endl;
}
char* func2(){
cout << "func2" << endl;
return "abc";
}
typedef void(*f_p)();
void main(){
//函數指針數組
f_p f_array[];
f_array[] = func1;
//C的寫法
//f_array[1] = (f_p)(func2);
//C++方式
f_array[] = reinterpret_cast<f_p>(func2);
//調用方法
f_array[]();
}
記憶體配置設定
1、C++ 通過new(delete)動态記憶體配置設定
- 使用new的方式:和malloc一樣的功能,但是會自動調用構造函數
- 使用delete的方式:和free一樣的功能,但是會自動調用析構函數
- 指針的malloc、free可以和new、delete互相摻雜使用,但是malloc、free不會調用構造函數和析構函數
class Teacher{
private:
char* name;
public:
Teacher(char* name){
this->name = name;
cout << "Teacher有參構造函數" << endl;
}
~Teacher(){
cout << "Teacher析構函數" << endl;
}
void setName(char* name){
this->name = name;
}
char* getName(){
return this->name;
}
};
void func(){
Teacher *t1 = new Teacher("jack");
cout << t1->getName() << endl;
delete t1;
}
void main(){
func();
}
運算符重載
1、運算符重載的寫法一
class Point{
public:
int x;
int y;
public:
Point(int x = , int y = ){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
};
//重載+号
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
//重載-号
Point operator-(Point &p1, Point &p2){
Point tmp(p1.x - p2.x, p1.y - p2.y);
return tmp;
}
void main(){
Point p1(,);
Point p2(,);
Point p3 = p1 + p2;
//輸出結果30,30
p3.myprint();
}
2、運算符重載的寫法二
class Point{
public:
int x;
int y;
public:
Point(int x = , int y = ){
this->x = x;
this->y = y;
}
//成員函數,運算符重載
Point operator+(Point &p2){
Point tmp(this->x + p2.x, this->y + p2.y);
return tmp;
}
void myprint(){
cout << x << "," << y << endl;
}
};
void main(){
Point p1(, );
Point p2(, );
//運算符的重載,本質還是函數調用
//p1.operator+(p2)
Point p3 = p1 + p2;
p3.myprint();
}
3、通過友元函數和運算符重載通路私有變量
class Point{
friend Point operator+(Point &p1, Point &p2);
private:
int x;
int y;
public:
Point(int x = , int y = ){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
};
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
void main(){
Point p1(, );
Point p2(, );
//運算符的重載,本質還是函數調用
//p1.operator+(p2)
Point p3 = p1 + p2;
p3.myprint();
}
其他
1、布爾類型(bool)
布爾類型的值大于0的都為true,布爾類型的值小于等于0的都為false
2、三目運算符
三目運算符可以作為參數進行指派
int a = , b = ;
((a > b) ? a : b) = ;
3、指針常量與常量指針
- 指針常量(int *const p):指針的常量,表示不可以修改p的位址,但是可以修改p的内容
- 常量指針(const int *p):指向常量的指針,表示不可以修改p的内容,但是可以修改p的位址
4、指針函數與函數指針
- 指針函數(int *fun(x,y)):指向指針的函數,其實可以說是傳回指針的函數
- 函數指針(int (*fun)(x,y);funa = fun;funb = fun;):指向函數的指針