基礎知識
- C++的源文件擴展名是:cpp(c plus plus)
- C++程序的入口是main函數(shù)(函數(shù)既方法扁达,一個意思)
- C++完全兼容C語言的語法待诅,很久之前统求,C++叫做C with classes
發(fā)展歷史
截屏2021-02-09 下午1.57.33.png
cin乘碑、cout
- C++中常使用cin挖息、cout進行控制臺的輸入和輸出
- cin用的是右移運算符 >> ,count用的是左移運算符 <<
- endl 是換行運算符
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
int age;
cin >> age;
cout << "age is " << age << endl;
return 0;
}
函數(shù)重載(Overload)
- 規(guī)則
- 函數(shù)名相同
- 參數(shù)個數(shù)兽肤、參數(shù)順序套腹、參數(shù)類型不同
- 注意
- 返回值類型函數(shù)重載無關
- 調(diào)用函數(shù)時,實參的隱式類型類型轉換可能會產(chǎn)生二義性
- 本質
- 采用了name mangling或者叫name decoration技術
- C++編譯器默認會對符號名(變量名资铡、函數(shù)名等)進行改編电禀、修飾,有些地方翻譯為“命名傾軋”
- 重載時會產(chǎn)生多個不同的函數(shù)名笤休,不同編譯器(MSVC尖飞、g++)有不同的生成規(guī)則
- 用過IDA打開【VS_Release_禁止優(yōu)化】可以看到
- 采用了name mangling或者叫name decoration技術
#include <iostream>
using namespace std;
// display_v
void display() {
cout << "display() " << endl;
}
// display_i
void display(int a) {
cout << "display(int a) " << a << endl;
}
// display_l
void display(long a) {
cout << "display(long a) " << a << endl;
}
// display_d
void display(double a) {
cout << "display(double a) " << a << endl;
}
int main(int argc, const char * argv[]) {
display();
display(10);
display(10l);
display(10.1);
return 0;
}
extern "C"
- 被extern "C" 修飾的代碼會按照C語言的方式去編譯
extern "C" void func() {
cout << "func" << endl;
}
extern "C" void func2(int age) {
cout << "func(int age)" << age << endl;
}
extern "C" {
void func3(){
cout << "func()" << endl;
}
void func4(int age) {
cout << "func(int age)" << age << endl;
}
}
- 如果函數(shù)同時有聲明和實現(xiàn),要讓函數(shù)聲明extern “C” 修飾,函數(shù)實現(xiàn)不可以修飾
extern "C" void func();
extern "C" void func2(int a);
extern "C" {
void func3();
void func4(int a);
}
void func() {
cout << "func()" << endl;
}
void func2(int a) {
cout << "func(int a) " << a << endl;
}
- 由于C政基、C++編譯器規(guī)則的不同贞铣,在C、C++混合開發(fā)時候沮明,可能會出現(xiàn)以下操作
- C++在調(diào)用C語言API的時候辕坝,需要使用extern "C" 修飾C語言的函數(shù)聲明
- 有時候也會在編寫C語言代碼中直接使用extern "C",這樣可以直接被C++調(diào)用
- 通過使用宏__cplusplus來區(qū)分C荐健、C++環(huán)境
// sum.h
#ifndef __SUM_H
#define __SUM_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
int sum(int a, int b);
int minus(int a, int b);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !__SUM_H
// sum.c
#include "sum.h"
// _sum
int sum(int a, int b) {
return a + b;
}
int minus(int a, int b) {
return a - b;
}
// main.cpp
#include <iostream>
#include "sum.h"
using namespace std;
int main(int argc, const char * argv[]) {
cout << sum(10, 20) << endl;
return 0;
}
默認參數(shù)
- C++ 允許函數(shù)設置默認參數(shù)酱畅,在調(diào)用時可以根據(jù)情況省略實參,規(guī)則如下:
- 默認參數(shù)只能按照右到左的順序
- 如果函數(shù)同時有聲明江场、實現(xiàn)圣贸,默認參數(shù)只能放在函數(shù)聲明中
- 默認參數(shù)的值可以是常量、全局符號(全局變量扛稽、函數(shù)名)
#include <iostream>
using namespace std;
int age = 33;
void test() {
cout << "test()" << endl;
}
void display(int a = 11, int b = 22, int c = age, void (*func)() = test) {
cout << "a is " << a << endl;
cout << "b is " << b << endl;
cout << "c is " << c << endl;
func();
}
int main(int argc, const char * argv[]) {
display();
return 0;
}
- 函數(shù)重載吁峻、默認參數(shù)可能會產(chǎn)生沖突、二義性(建議優(yōu)先選擇默認參數(shù))
#include <iostream>
using namespace std;
void display(int a, int b = 20) {
cout << "a is" << a << endl;
}
void display(int a) {
cout << "a is" << a << endl;
}
int main(int argc, const char * argv[]) {
// Call to 'display' is ambiguous
display(10);
return 0;
}
內(nèi)聯(lián)函數(shù)
- 使用inline修飾函數(shù)的聲明或者實現(xiàn)在张,可以使其變成內(nèi)聯(lián)函數(shù)
- 建議聲明和實現(xiàn)都增加inline修飾
- 特點
- 編譯器會將函數(shù)調(diào)用直接展開為函數(shù)體代碼
- 可以減少函數(shù)調(diào)用的開銷
- 會增大代碼體積
- 注意
- 盡量不要內(nèi)聯(lián)超過10行代碼的函數(shù)
- 有些函數(shù)即使聲明為inline用含,也不一定會被編譯器內(nèi)聯(lián),比如遞歸函數(shù)帮匾。
#include <iostream>
using namespace std;
inline int sum(int a, int b);
int main() {
sum(10, 20);
getchar();
return 0;
}
inline int sum(int a, int b) {
return a + b;
}
內(nèi)聯(lián)函數(shù)與宏
- 內(nèi)聯(lián)函數(shù)與宏啄骇,都可以減少函數(shù)調(diào)用的開銷
- 對比宏,內(nèi)聯(lián)函數(shù)多了語法檢測和函數(shù)特性
#pragma once
- 我們經(jīng)常使用
#ifndef
瘟斜、#define
缸夹、#endif
來防止頭文件內(nèi)容被重復包含 -
#pragma once
可以防止整個文件的內(nèi)容被重復包含 - 區(qū)別
-
#ifndef
、#define
螺句、#endif
受C\C++標準的支持虽惭,不受編譯器的任何限制 - 有些編譯器不支持
#pragma once
(較老編譯器不支持,如GCC 3.4版本之前的)蛇尚,兼容性不夠好 -
#ifndef
芽唇、#define
、#endif
可以針對一個文件中的部分代碼取劫,而#pragma once
只能針對整個文件
-