C 是面向過程的語言,而 C ++ 是面向?qū)ο蟮恼Z言。
C ++ 在某種程度上,可以理解為 C 語言強(qiáng)化版。兩種語言有不少相似之處,且大部分時(shí)候,C ++ 可以兼容 C 語言。C ++ 可以直接運(yùn)行 C 語言函數(shù),但 C 語言不能調(diào)用 C ++。
C ++ 中,const 常量的不可變性得到了支持,而在 C 中,函數(shù)定義的 const 常量,可以通過指針修改。
C ++ 支持函數(shù)重載(同名函數(shù),不同參數(shù)),C 不支持(C 函數(shù)名稱不可重復(fù));C++ 的函數(shù)支持默認(rèn)參數(shù),C 和java 都不支持。
C ++ 有 string、bool 類型,而 C 中沒有專門的string、bool;但二者都是非 0 即 true
命名空間
命名空間,作用類似于 java 中的包名,為了在引用時(shí)區(qū)分不同庫中定義的同名函數(shù)或變量。
命名空間可以用雙冒號(hào)(::)表示;也可以直接在文件中用using指示進(jìn)行聲明,使得特定命名空間的所有名字可見
#include <stdio.h>
#include <iostream>
int main() {
// C ++ 中,可以調(diào)用 C 語言的輸出方法
printf("this is a C output in C++\n");
// C ++ 自己的輸出方法
// << 運(yùn)算符被重載,此處并不是左移,而是輸出流拼接,可以理解為輸出格式
std::cout << "this is a C++ couput" << std::endl;
return 0;
}
// 直接聲明命名空間
//using namespace std;
//
//int main() {
// //聲明命名空間后,無需再用 std:: 方式指明函數(shù)的所在
// cout << "this is the output with namespace" << endl;
// return 0;
//}
自定義命名空間
命名空間的定義一般置于 .hpp 的頭文件中,作為對(duì)外開放的接口聲明。
// 自定義一個(gè)命名空間
namespace bynamespace {
// 命名空間可以有變量
char * property;
// 類
class ObjectManager {
private:
char *className;
public:
char * getClassName();
void setClassName(char *className);
};
// 方法
void function(ObjectManager manager);
// 方法可能與其他命名空間的方法沖突
void cout();
// 命名空間內(nèi)還可以嵌套命名空間
namespace subnamespace {
void sayHello();
}
}
// 添加命名空間引用
using namespace std;
using namespace bynamespace;
int main() {
// 由于添加了引用,可以省略命名空間的名稱
ObjectManager manager = ObjectManager();
bynamespace::function(manager);
// 嵌套的命名空間,在沒有添加命名空間引用時(shí),應(yīng)為:bynamespace::subnamespace::sayHello();
subnamespace::sayHello();
// 當(dāng)兩個(gè)命名空間內(nèi)方法沖突時(shí),不可以省略命名空間名稱,即便已經(jīng)添加了引用
bynamespace::cout();
std::cout << "print" << endl;
return 0;
}
函數(shù)特性
C++ 中,函數(shù)支持重載和傳參默認(rèn)值,但是默認(rèn)值不似 kotlin 中那般靈活。C++ 中函數(shù)的參數(shù)默認(rèn)值,必須從右往左進(jìn)行默認(rèn)值設(shè)置;在調(diào)用時(shí),必須從左到右,傳入?yún)?shù)。
且在函數(shù)聲明時(shí),需注意,要避開默認(rèn)值可能帶來的函數(shù)重載。
using namespace std;
// 全賦值默認(rèn)參數(shù);此方法在調(diào)用時(shí),無法跳過 a、b 直接給 c、d 賦值
int sum(string s, int a = 0, int b = 0, int c = 0, int d = 0) {
// sum(); -> a: 0, b: 0, c: 0, d: 0
// sum(1, 2); -> a: 1, b:2, c:0, d:0
// sum(1, 2, 3, 4); -> a: 1, b:2, c:3, d:4
cout << "a: " << a << ", b:" << b << ", c:" << c << ", d:" << d << endl;
return a + b + c + d;
}
// 不能這樣賦值默認(rèn)值,必須從右到左填充,填充完 a,之后才可以填充 s
// int sum(string s = "abc", int a, int b = 0, int c = 0, int d = 0)
// 此方法無法再進(jìn)行聲明,因?yàn)樵谏厦娴膕um中,已經(jīng)包含了兩個(gè) int 參數(shù)的重載
// 但在聲明方法時(shí),并不會(huì)報(bào)錯(cuò),而是在使用方法時(shí)報(bào)錯(cuò)
// int sum(string a, int b);
// 此方法可以重載,因?yàn)樯厦婺J(rèn)值的方法第一個(gè)參數(shù)是 string,重載的方法,需從左到右保留參數(shù)
int sum(int a, int b);
int main() {
int t1 = sum("test1");
int t2 = sum("test2", 1, 2);
int t3 = sum("test3", 1, 2, 3, 4);
// 如果上面聲明了 int sum(string a, int b) 方法,則會(huì)報(bào)錯(cuò):Call to 'sum' is ambiguous
// int t4 = sum("test4", 1);
cout << "t1: " << t1 << ", t2:" << t2 << ", t3:" << t3 << endl;
return 0;
}
此外,在 C 或者 C++ 中,函數(shù)的參數(shù)聲明,可能只有類型,而沒有參數(shù)名。
一般這種沒有參數(shù)名的函數(shù)聲明,只是用于 .h 的聲明中,在后續(xù)的實(shí)現(xiàn)函數(shù)中還是需要填寫名稱的,否則沒有參數(shù)名的形參無法在函數(shù)體內(nèi)被使用。
// 在參數(shù)聲明時(shí),只有類型 int,沒有參數(shù)名
void printInfo(const int &, int);
// 調(diào)用時(shí)需要傳入一個(gè) string 類型,但是并沒有任何用處,不建議這么寫
void printInfo(string) {
cout << endl;
}
int main() {
int a = 100;
// 調(diào)用時(shí),必須傳遞該 int 類型參數(shù)
printInfo(a, 0);
return 0;
}
void printInfo(const int &value, int level) {
cout << "value: " << value << ", level: " << level << endl;
}
靜態(tài)變量
靜態(tài)變量可以直接在函數(shù)外部進(jìn)行定義,全局可用。
static int DEBUG = 1;
在類中,需要先聲明的靜態(tài)變量,然后再初始化
class Test {
public:
// 先聲明
const int a;
}
// 再初始化
int Test::a = 10;
可變參數(shù)
C 和 C++ 中,都支持 ... 可變參數(shù)。
但與java 不同的是,無法自動(dòng)識(shí)別參數(shù)個(gè)數(shù)。
因而一般在定義時(shí),都會(huì)在參數(shù)前添加 int cout 參數(shù)聲明接下來的 ...包含幾個(gè)變量。
... 參數(shù)必須位于最后一個(gè)位置。
... 支持傳入不同的基本類型(不支持自定義類型),但需要在解析的時(shí)候按順序解析。
在使用 ... 參數(shù)時(shí),需要先創(chuàng)建 va_list 類型變量用于存儲(chǔ)這一系列參數(shù)。
通過 va_start(args, count) 將變量的值轉(zhuǎn)移到 va_list 中;其中 count 變量需要傳值 ... 的前一個(gè)函數(shù)入?yún)ⅰ?br>
通過 va_arg(ags, int) 方法,將 args 中的參數(shù)取出,其中int 為對(duì)應(yīng)參數(shù)的類型。
最后需要用 va_end(args) 結(jié)束 args 的讀取。
int sum(int count, ...) {
int result = 0;
// 創(chuàng)建存儲(chǔ)入?yún)⒌淖兞? va_list args;
// va_start 將入?yún)⒆x取到 args 中,需要 ... 參數(shù)的前一個(gè)參數(shù)作為讀取錨點(diǎn)
va_start(args, count);
for (int i = 0; i < count; i++) {
// va_arg 讀取 args 中的參數(shù),需要傳入對(duì)應(yīng)的數(shù)據(jù)類型
result += va_arg(args, int);
}
// 結(jié)束讀取后,需要調(diào)用 var_end 方法
va_end(args);
return result;
}
int main() {
cout << sum(2, 10, 20) << endl;
return 0;
}