可變參數
#include <iostream>
#include <stdarg.h> // 可變參數的支持
using namespace std;
// Java的可變參數: int ...
// C++的可變參數寫法:...
// count的第一個用處:內部需要一個 存儲地址用的參考值,如果沒有這個參數,內部他無法處理存放參數信息
void sum(int count, ...) {
va_list vp; // 可變參數的動作
// 參數一:可變參數開始的動作vp
// 參數二:內部需要一個 存儲地址用的參考值,如果沒有第二個參數,內部他無法處理存放參數信息
va_start(vp, count);
// 到這裏後:vp就已經有豐富的信息
// 取出可變參數的一個值
int number = va_arg(vp, int);
cout << number << endl;
// 取出可變參數的一個值
number = va_arg(vp, int);
cout << number << endl;
// 取出可變參數的一個值
number = va_arg(vp, int);
cout << number << endl;
// 越界 系統值 亂碼
// 取出可變參數的一個值 【取不到後,會取系統值 亂碼】
number = va_arg(vp, int);
cout << number << endl;
// 關閉階段
va_end(vp);
}
// 1.可變參數
int main() {
std::cout << "同學們大家好,我是Derry" << std::endl;
sum(546, 6,7,8);
return 0;
}
可變參數count變量的第二個用處
#include <iostream>
#include <stdarg.h> // 可變參數的支持
using namespace std;
// Java的可變參數: int ...
// C++的可變參數寫法:...
// count變量的第二個用處,用於循環遍歷長度
void sum(int count, ...) {
va_list vp; // 可變參數的動作
// 參數一:可變參數開始的動作vp
// 參數二:內部需要一個 存儲地址用的參考值,如果沒有第二個參數,內部他無法處理存放參數信息
va_start(vp, count);
// 到這裏後:vp就已經有豐富的信息
for (int i = 0; i < count; ++i) {
int r = va_arg(vp, int);
cout << r << endl;
}
// 關閉階段(規範:例如:file文件一樣 要關閉)
va_end(vp);
}
// 1.可變參數
int main() {
sum(3, 6,7,8); // 真實開發過程的寫法
return 0;
}
static關鍵字==錯誤==示範
// 2.C++static關鍵字。 錯誤的寫法
#include <iostream>
using namespace std;
class Dog {
public:
char * info;
int age;
// 已經編譯不成功,不允許這樣初始化
// static int id = 9;
static int id;
Dog() {
// 運行報錯
// id = 9;
}
static void update() {
// 運行報錯
// id = 9;
}
void update2() {
// 運行報錯
// id = 9;
}
};
int main() {
Dog dog;
Dog::update(); // 類名::可以調用靜態函數
return 0;
}
static關鍵字==正確寫法==
// 2.C++static關鍵字。 正確的寫法
/**
* 靜態的總結:
* 1.可以直接通過類名::靜態成員(字段/函數)
* 2.靜態的屬性必須要初始化,然後再實現(規則)
* 3.靜態的函數只能取操作靜態的屬性和方法(Java)
*/
#include <iostream>
using namespace std;
class Dog {
public:
char * info;
int age;
// 先聲明
static int id;
static void update() {
id += 100;
// 報錯:靜態函數不能調用非靜態函數(Java)
// update2();
}
void update2() {
id = 13;
}
};
// 再實現
int Dog::id = 9;
int main() {
Dog dog;
dog.update2(); // 普通函數
Dog::update(); // 靜態函數
dog.update(); // 對象名.靜態函數(一般都是使用::調用靜態成員,這種方式可以 知道就行)
cout << Dog::id << endl;
return 0;
}
this
#include <iostream> // iostream.h 早期C++的方式
using namespace std;
class Student {
private:
char *name;
int age;
public:
static int id; // 先聲明
public:
void setName(char *name) {
this->name = name;
}
void setAge(int age) {
this->age = age;
}
char *getName() {
return this->name;
}
int getAge() {
return this->age;
}
public:
// 默認的構造函數 棧區開闢空間 暴露 地址 == this指針 (和Java一致的思路)
};
// 再實現
int Student::id = 9527;
int main() {
//四大區:棧區、堆區、全局區(靜態區、常量區、字符串區)、代碼區
// ======= 常規使用下而已
Student student;
student.setAge(99);
student.setName("Derry");
cout << student.getName() << " , " << student.getAge()<< endl;
// ========== this 糾結 setAge在代碼區,有多個副本,對應不用指針
Student student1;
student1.setAge(88); // 設置值的時候,它怎麼知道是給student1的age設置值的?
student1.id = 880;
Student student2;
student2.setAge(99); // 設置值的時候,它怎麼知道是給student2的age設置值的?
student2.id = 990;
Student::id = 666;
// 它怎麼知道是獲取student1的age
cout << " student1.getAge:" << student1.getAge() << endl;
// 它怎麼知道是獲取student2的age
cout << " student2.getAge:" << student2.getAge() << endl;
cout << "student1.id:" << student1.id << endl;
cout << "student2.id:" << student2.id << endl;
cout << "Student:::" << Student::id << endl;
return 0;
} // main函數彈棧會 隱式代碼:(棧區:delete student ..., 堆區需要自己手動delete)
const修飾函數的this意義何在
#include <iostream>
using namespace std;
// 如果是面試C++崗位,會被回到,不然問不到
class Worker {
public:
char * name;
int age = NULL; // C++中不像Java,Java有默認值, 如果你不給默認值,那麼就是系統值 -64664
// int * const 指針常量 指針常量【地址對應的值能改,地址不可以修改】
// const int * 常量指針 常量指針【地址可以修改,地址對應的值不能改】
// 糾結:原理:爲什麼可以修改age
// 默認持有隱式的this【類型 * const this】
// 類型 * const 指針常量:代表指針地址不能被修改,但是指針地址的值是可以修改的
void change1() {
// 代表指針地址不能被修改
// this = 0x6546; // 編譯不通過,地址不能被修改,因爲是指針常量
// 地址不可以修改
// this = 0x43563;
// 隱士的this
// 但是指針地址的值是可以修改的
// 地址對應的值能改
this->age = 100;
this->name = "JJJ";
}
// 默認現在:this 等價於 const Student * const 常量指針常量(地址不能改,地址對應的值不能改)
void changeAction() const {
// 地址不能改
// this = 0x43563;
// 地址對應的值不能改
// this->age = 100;
}
// 原理:修改隱式代碼 const 類型 * const 常量指針常量
void showInfo() const {
// this->name = "";
// this->age = 88;
// 只讀的
cout << "age:" << age << endl;
}
};
int main() {
return 0;
}
友元函數
// 老外:你是它的好朋友,那就可以拿私有成員給好朋友
#include <iostream>
using namespace std;
class Person {
private: // 私有的age,外界不能訪問
int age = 0;
public:
Person(int age) {
this->age = age;
}
int getAge() {
return this->age;
}
// 定義友元函數 (聲明,沒有實現)
friend void updateAge(Person * person, int age);
};
// 友元函數的實現,可以訪問所以私有成員
void updateAge(Person* person, int age) {
// 默認情況下:不能修改 私有的age
// 誰有這個權限:友元(拿到所有私有成員)
person->age = age;
}
int main() {
Person person = Person(9);
updateAge(&person, 88);
cout << person.getAge() << endl;
return 0;
}
實際寫法
#include <iostream>
using namespace std;
#ifndef PIG_H // 你有沒有這個宏(Java 宏==常量)
#define PIG_H // 定義這個宏
class Pig {
private:
int age;
char * name;
public:
// 靜態成員聲明
static int id;
// 構造函數的聲明系列
Pig();
Pig(char *);
Pig(char *,int);
// 析構函數
~Pig();
// 拷貝構造函數
Pig(const Pig & pig);
// 普通函數 set get
int getAge();
char * getName();
void setAge(int);
void setName(char *);
void showPigInfo() const; // 常量指針常量 只讀
// 靜態函數的聲明
static void changeTag(int age);
// 不要這樣幹
// void changeTag(int age);
// 友元函數的聲明
friend void changeAge(Pig * pig, int age);
};
#endif // 關閉/結尾
#include "Pig.h"
// TODO ====================== 下面是 普普通通 常規操作 對象::
// 實現構造函數
Pig::Pig() {
cout << "默認構造函數" << endl;
}
Pig::Pig(char * name) {
cout << "1個參數構造函數" << endl;
}
Pig::Pig(char * name, int age) {
cout << "2個參數構造函數" << endl;
}
// 實現析構函數
Pig::~Pig() {
cout << "析構函數" << endl;
}
// 實現 拷貝構造函數
Pig::Pig(const Pig &pig) {
cout << "拷貝構造函數" << endl;
}
int Pig::getAge() {
return this->age;
}
char * Pig::getName() {
return this->name;
}
void Pig::setAge(int age) {
this->age = age;
}
void Pig::setName(char * name) {
this->name = name;
}
void Pig::showPigInfo() const {
} // 常量指針常量 只讀
// TODO =============================== 靜態 和 友元 注意點 自己理解
// 實現 靜態屬性【不需要增加 static關鍵字】
int Pig::id = 878;
// 實現靜態函數,【不需要增加 static關鍵字】
void Pig::changeTag(int age) {
}
// 友元的實現
// 友元特殊:不需要關鍵字,也不需要 對象:: ,只需要保證 函數名(參數)
void changeAge(Pig * pig, int age) {
}
友元類
// 友元類 的 小故事 (ImageView 私有成員 可以通過Class來訪問,但是Class操作的native C++代碼)
// 下載 JDK native代碼 研究 【自己去研究】
// ImageView 私有成員 你能訪問它的私有成員嗎 Class
#include <iostream>
using namespace std;
class ImageView {
private:
int viewSize;
friend class Class; // 友元類
};
// Java每個類,都會有一個Class,此Class可以操作 ImageView私有成員(感覺很神奇)
class Class {
public:
ImageView imageView;
void changeViewSize(int size) {
imageView.viewSize = size;
}
int getViewSize() {
return imageView.viewSize;
}
};
int main() {
Class mImageViewClass;
mImageViewClass.changeViewSize(600);
cout << mImageViewClass.getViewSize() << endl;
return 0;
}