您好,登錄后才能下訂單哦!
C C++ 是干什么的
1簡單的C++ Hello World!
#include "iostream" using namespace std; int main() { cout << "Hello World!\n" ;//<< endl; cout << "Hello World!" << endl; return 0; } 編譯運行: chunli@Linux:~/c++$ g++ main.cpp && ./a.out Hello World! Hello World! chunli@Linux:~/c++$
2面向對象的認識:
求圓的面積,過程方法
#include "iostream" using namespace std; int main() { double r = 0; double s = 0; cout << "請輸入圓的半徑:" ;//<< endl; cin >> r; s = 3.1415926 * r * r; cout <<"圓的面積是:"<< s << endl; return 0; } 編譯: chunli@Linux:~/c++$ g++ main.cpp && ./a.out 請輸入圓的半徑:10 圓的面積是:314.159
求圓的面積,面向對象方法
#include "iostream" using namespace std; //類是一個數據類型,(固定大小內存塊的別名); //定義一個類,是一個抽象的概念,不會給你分配內存 //用數據類型定義變量的時候,才會分配內存 class MyCicle { public : double m_s; double m_r; void set_R(double r) { m_r = r; } double gets() { return 3.1415926 * m_r * m_r; } }; int main() { MyCicle my1; double r; cout << "請輸入圓的半徑:" ; cin >> r; my1.set_R(r); cout <<"圓的面積是:"<< my1.gets() << endl; return 0; } 編譯運行: chunli@Linux:~/c++$ g++ main.cpp && ./a.out 請輸入圓的半徑:11 圓的面積是:380.133
【經典】初學者易犯錯誤:
#include "iostream" using namespace std; class MyCicle { public : double r; double s = 3.14 * r *r; }; int main() { MyCicle my1; cout << "請輸入圓的半徑:" ; cin >> my1.r; cout <<"圓的面積是:"<< my1.s << endl; return 0; } 編譯運行:Lchunli@Linux:~/c++$ g++ -std=c++11 main.cpp && ./a.out 請輸入圓的半徑:10 圓的面積是:0
namespace 1,標準用法:
因為iostream中沒有引入標準std,需要程序員手工寫
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { cout << "Hello World!"<<endl ; return 0; } 編譯運行: chunli@Linux:~/c++$ g++ main.cpp && ./a.out Hello World!
namespace 2,實際用法:
如果不寫 using namespace std ,那么需要顯式的引入std
chunli@Linux:~/c++$ cat main.cpp #include "iostream" //using namespace std; int main() { std::cout << "Hello World!"<<std::endl ; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out Hello World!
自定義namespace
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; namespace namespaceA { int a ; } namespace namaspaceB { int a ; namespace namaspaceC { int a ; } } int main() { using namespace namespaceA; a = 10; cout << a <<endl ; return 0; } 編譯運行: chunli@Linux:~/c++$ g++ main.cpp && ./a.out 10
兩個namespace中含有同樣的變量,編譯不通過
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; namespace namespaceA { int a ; } namespace namespaceB { int a ; namespace namespaceC { int a ; } } int main() { using namespace namespaceA; using namespace namespaceB; a = 10; cout << a <<endl ; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out main.cpp: In function ‘int main()’: main.cpp:24:2: error: reference to ‘a’ is ambiguous a = 10; ^ 可以看到不明確a是哪一個
顯式的引用不同namespace中的值
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; namespace namespaceA { int a ; } namespace namespaceB { int a ; namespace namespaceC { int a ; } } int main() { using namespace namespaceA; using namespace namespaceB; namespaceA::a = 10; namespaceB::a = 20; cout << namespaceA::a <<endl ; cout << namespaceB::a <<endl ; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out 10 20
使用嵌套的namespace
#include "iostream" using namespace std; namespace namespaceB { int a ; namespace namespaceC { struct Teacher { int age; }; } } int main() { using namespace namespaceB::namespaceC; Teacher t1; t1.age =10; cout << t1.age<<endl ; return 0; } 編譯: chunli@Linux:~/c++$ g++ main.cpp && ./a.out 10
=============================================================================
C++與C的區別:
1
2 register類型增強
chunli@Linux:~/c++$ cat 123.c #include <stdio.h> int main() { register int a = 0; printf("%p \n",&a); return 0; } C語言編譯不通過: chunli@Linux:~/c++$ gcc 123.c && ./a.out 123.c: In function ‘main’: 123.c:5:2: error: address of register variable ‘a’ requested printf("%p \n",&a); ^ C++編譯通過: chunli@Linux:~/c++$ g++ 123.c && ./a.out 0x7ffe7ac2cc3c
C語言缺陷,C++修復
chunli@Linux:~/c++$ cat 123.c #include <stdio.h> f(i) { printf("i = %d \n",i); } g() { return 5; } int main() { f(10); printf("%d \n",g()); printf("%d \n",g(1,2,3,4)); return 0; } C語言編譯OK chunli@Linux:~/c++$ gcc 123.c && ./a.out i = 10 5 5 C++編譯報錯: chunli@Linux:~/c++$ g++ 123.c && ./a.out 123.c:2:2: error: expected constructor, destructor, or type conversion before ‘(’ token f(i) ^ 123.c:6:3: error: ISO C++ forbids declaration of ‘g’ with no type [-fpermissive] g() ^
C++對C的加強:
1 namespace命名空間
1 C++命名空間基本常識
所謂namespace,是指標識符的各種可見范圍。C++標準程序庫中的所有標識符都被定義于一個名為std的namespace中。
一 :<iostream>和<iostream.h>格式不一樣,前者沒有后綴,實際上,在你的編譯器include文件夾里面可以看到,二者是兩個文件,打開文件就會發現,里面的代碼是不一樣的。后綴為.h的頭文件c++標準已經明確提出不支持了,早些的實現將標準庫功能定義在全局空間里,聲明在帶.h后綴的頭文件里,c++標準為了和C區別開,也為了正確使用命名空間,規定頭文件不使用后綴.h。 因此,
1)當使用<iostream.h>時,相當于在c中調用庫函數,使用的是全局命名空間,也就是早期的c++實現;
2)當使用<iostream>的時候,該頭文件沒有定義全局命名空間,必須使用namespace std;這樣才能正確使用cout。
二: 由于namespace的概念,使用C++標準程序庫的任何標識符時,可以有三種選擇:
1、直接指定標識符。例如std::ostream而不是ostream。完整語句如下: std::cout << std::hex << 3.4 << std::endl;
2、使用using關鍵字。 using std::cout; using std::endl; using std::cin; 以上程序可以寫成 cout << std::hex << 3.4 << endl;
3、最方便的就是使用using namespace std; 例如: using namespace std;這樣命名空間std內定義的所有標識符都有效(曝光)。就好像它們被聲明為全局變量一樣。那么以上語句可以如下寫: cout <<hex << 3.4 << endl;因為標準庫非常的龐大,所以程序員在選擇的類的名稱或函數名 時就很有可能和標準庫中的某個名字相同。所以為了避免這種情況所造成的名字沖突,就把標準庫中的一切都被放在名字空間std中。但這又會帶來了一個新問 題。無數原有的C++代碼都依賴于使用了多年的偽標準庫中的功能,他們都是在全局空間下的。所以就有了<iostream.h> 和<iostream>等等這樣的頭文件,一個是為了兼容以前的C++代碼,一個是為了支持新的標準。命名空間std封裝的是標準程序庫的名稱,標準程序庫為了和以前的頭文件區別,一般不加".h"
4.2 “實用性”增加
#include "iostream" using namespace std; //C語言中的變量都必須在作用域開始的位置定義!! //C++中更強調語言的“實用性”,所有的變量都可以在需要使用時再定義。 int main11() { int i = 0; printf("ddd"); int k; system("pause"); return 0; }
4.3 register關鍵字增強
//register關鍵字 請求編譯器讓變量a直接放在寄存器里面,速度快 //在c語言中 register修飾的變量 不能取地址,但是在c++里面做了內容 /* //1 register關鍵字的變化 register關鍵字請求“編譯器”將局部變量存儲于寄存器中 C語言中無法取得register變量地址 在C++中依然支持register關鍵字 C++編譯器有自己的優化方式,不使用register也可能做優化 C++中可以取得register變量的地址 //2 C++編譯器發現程序中需要取register變量的地址時,register對變量的聲明變得無效。 //3 早期C語言編譯器不會對代碼進行優化,因此register變量是一個很好的補充。 */ int main22() { register int a = 0; printf("&a = %x\n", &a); system("pause"); return 0; }
4.4變量檢測增強
/* 在C語言中,重復定義多個同名的全局變量是合法的 在C++中,不允許定義多個同名的全局變量 C語言中多個同名的全局變量最終會被鏈接到全局數據區的同一個地址空間上 int g_var; int g_var = 1; C++直接拒絕這種二義性的做法。 */ int main(int argc, char *argv[]) { printf("g_var = %d\n", g_var); return 0; }
4.5 struct類型加強
struct類型的加強:
C語言的struct定義了一組變量的集合,C編譯器并不認為這是一種新的類型
C++中的struct是一個新類型的定義聲明
struct Student { char name[100]; int age; }; int main(int argc, char *argv[]) { Student s1 = {"wang", 1}; Student s2 = {"wang2", 2}; return 0; }
4.6 C++中所有的變量和函數都必須有類型
/* C++中所有的變量和函數都必須有類型 C語言中的默認類型在C++中是不合法的 函數f的返回值是什么類型,參數又是什么類型? 函數g可以接受多少個參數? */ //更換成.cpp試試 f(i) { printf("i = %d\n", i); } g() { return 5; } int main(int argc, char *argv[]) { f(10); printf("g() = %d\n", g(1, 2, 3, 4, 5)); getchar(); return 0; }
【總結】:
/*
在C語言中
int f( );表示返回值為int,接受任意參數的函數
int f(void);表示返回值為int的無參函數
在C++中
int f( );和int f(void)具有相同的意義,都表示返回值為int的無參函數
*/
C++更加強調類型,任意的程序元素都必須顯示指明類型
4.2-4.6屬于語法級別的增強。
4.7新增Bool類型關鍵字
/* C++中的布爾類型 C++在C語言的基本類型系統之上增加了bool C++中的bool可取的值只有true和false 理論上bool只占用一個字節, 如果多個bool變量定義在一起,可能會各占一個bit,這取決于編譯器的實現 true代表真值,編譯器內部用1來表示 false代表非真值,編譯器內部用0來表示 bool類型只有true(非0)和false(0)兩個值 C++編譯器會在賦值時將非0值轉換為true,0值轉換為false */ int main(int argc, char *argv[]) { int a; bool b = true; printf("b = %d, sizeof(b) = %d\n", b, sizeof(b)); b = 4; a = b; printf("a = %d, b = %d\n", a, b); b = -4; a = b; printf("a = %d, b = %d\n", a, b); a = 10; b = a; printf("a = %d, b = %d\n", a, b); b = 0; printf("b = %d\n", b); system("pause"); return 0; }
4.8三目運算符功能增強
1三目運算符在C和C++編譯器的表現
int main() { int a = 10; int b = 20; //返回一個最小數 并且給最小數賦值成3 //三目運算符是一個表達式 ,表達式不可能做左值 (a < b ? a : b )= 30; printf("a = %d, b = %d\n", a, b); system("pause"); return 0; }
2結論
1)C語言返回變量的值 C++語言是返回變量本身
C語言中的三目運算符返回的是變量值,不能作為左值使用
C++中的三目運算符可直接返回變量本身,因此可以出現在程序的任何地方
2)注意:三目運算符可能返回的值中如果有一個是常量值,則不能作為左值使用
(a < b ? 1 : b )= 30;
3)C語言如何支持類似C++的特性呢?
====>當左值的條件:要有內存空間;C++編譯器幫助程序員取了一個地址而已
思考:如何讓C中的三目運算法當左值呢?
C++ bool類型
只要是非0數字賦予bool類型,全部為true
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { bool b1 = true; cout << sizeof(b1) << endl; b1 = 10; cout << b1 << endl; b1 = -10; cout << b1 << endl; b1 = 0; cout << b1 << endl; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out 1 1 1 0 chunli@Linux:~/c++$
C++ 對三目運算符的增強:
chunli@Linux:~/c++$ cat c.c #include<stdio.h> int main() { int a = 10; int b = 20; //在C語言中表達式返回值,返回變量的本身 //在++語言中返回變量本身 (a < b ? a: b) = 30; printf("%d \n",a); printf("%d \n",b); return 0; } chunli@Linux:~/c++$ gcc c.c && ./a.out c.c: In function ‘main’: c.c:6:17: error: lvalue required as left operand of assignment (a < b ? a: b) = 30; ^ chunli@Linux:~/c++$ g++ c.c && ./a.out 30 20
在C語言中如何實現在C++中編譯器的效果
C++編譯器幫程序員完成了剛才我們的動作
chunli@Linux:~/c++$ cat c.c #include<stdio.h> int main() { int a = 10; int b = 20; *(a < b ? &a: &b) = 30; printf("%d \n",a); printf("%d \n",b); return 0; } chunli@Linux:~/c++$ gcc c.c && ./a.out 30 20 chunli@Linux:~/c++$ g++ c.c && ./a.out 30 20
C++ const 基礎
#include "iostream" using namespace std; int main() { const int a = 10; int const b =11; //與上面的一樣 const int *c ; //指針指向的內存區域內的數值不能修改 int * const d; //指針不能亂指 const int * const e; //只讀指針 return 0; }
const C C++語言中的冒牌貨
1,C語言中的const真是個冒牌貨
chunli@Linux:~/c++$ cat c.c #include<stdio.h> int main() { const int a = 10; int *p = (int *)&a; *p = 20; printf("%d \n",a); return 0; } chunli@Linux:~/c++$ gcc c.c && ./a.out 20
2,C++語言中的const真是真貨
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { const int a = 10; int *p = NULL; p = (int *)&a; *p = 20; cout << a <<endl; cout << *p <<endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 10 20
const 與define
GCC支持這種寫法,微軟的不支持
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { int a =10; int b =30; int arr[a+b]; cout << sizeof(arr)/sizeof(int)<<endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 40
C++編譯器cosnt與宏定義 相似之處
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; #define a 20 int main() { //int a =10; int b =30; int arr[a+b]; cout << sizeof(arr)/sizeof(int)<<endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 50
宏定義作用范圍
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; void fun1() { #define a 20 cout << "Hello World!" << endl; } void fun2() { cout << a << endl; } int main() { fun1(); fun2(); return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out Hello World! 20
取消宏定義
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; void fun1() { #define a 20 cout << "Hello World!" << endl; #undef a //取消宏定義a //#undef //取消所有宏定義 } void fun2() { cout << a << endl; } int main() { fun1(); fun2(); return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out main.cpp: In function ‘void fun2()’: main.cpp:13:10: error: ‘a’ was not declared in this scope cout << a << endl; ^
【引用】
1,基礎知識,兩個變量的地址是一樣的
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { int a = 10; int &b = a; b = 20; cout<< a << endl; cout<< &a << endl; cout<< &b << endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 20 0x7ffec647cc94 0x7ffec647cc94 這就是傳說中的引用,不能用C語言去思考
1,定義一個引用,而沒有引用值,編譯報錯;
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int main() { int a = 10; cout << a << endl; int &b ; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out main.cpp: In function ‘int main()’: main.cpp:7:7: error: ‘b’ declared as reference but not initialized int &b ; ^
引用的實際應用,當函數參數
引用當函數參數不需要初始化
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; void fun1(int &a,int &b) { a = a ^ b; b = a ^ b; a = a ^ b; } void fun2(int *a,int *b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } int main() { int var1 = 10; int var2 = 20; cout << var1 << " "<<var2<< endl; fun1(var1,var2); cout << var1 << " "<<var2<< endl; fun2(&var1,&var2); cout << var1 << " "<<var2<< endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 10 20 20 10 10 20 chunli@Linux:~/c++$
復雜數據類型與引用;
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; struct Teacher { char name[64]; int age; }; void fun1(Teacher *p) { cout << p->age << endl; p->age = 11; } void fun2(Teacher &p) { cout << p.age << endl; p.age = 22; } void fun3(Teacher p) { cout << p.age << endl; p.age = 33; } int main() { Teacher t1; t1.age = 20; fun1(&t1); cout << "1 " << t1.age << endl; fun2(t1); cout << "2 " << t1.age << endl; fun3(t1); cout << "3 " << t1.age << endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 20 1 11 11 2 22 22 3 22 chunli@Linux:~/c++$
結構體的引用類型實質
可以看出與指針很像
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; struct Teacher { char &c; }; int main() { cout << sizeof(struct Teacher)<< endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 8
引用的本質,看圖
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; void fun1(int &a) { a = 10; } void fun2(int *a) { *a = 20; } int main() { int var = 0; fun1(var); cout << var<< endl; fun2(&var); cout << var<< endl; return 0; } chunli@Linux:~/c++$ g++ -Wall main.cpp && ./a.out 10 20
引用的難點:
返回引用數據類型的函數,用什么數據類型來接?
1,用普通變量來接,相當于數值的傳遞
2,用引用類型數據來接,相當于地址的傳遞(危險),返回的地址是已經被析構的
GCC會有警告
VS不會有警告
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int& fun1() { int a = 10; return a; } int main() { int a = fun1(); cout << a<< endl; int &b = fun1(); cout << b<< endl; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out main.cpp: In function ‘int& fun1()’: main.cpp:5:6: warning: reference to local variable ‘a’ returned [-Wreturn-local-addr] int a = 10; ^ 10 10
函數返回應用類型,變量是全局生命周期
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int a = 20; int& fun1() { return a; } int main() { int a = fun1(); cout << a<< endl; int &b = fun1(); cout << b<< endl; return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out 20 20
函數當左值,注意變量的生命周期
chunli@Linux:~/c++$ cat main.cpp #include "iostream" using namespace std; int a = 20; int& fun1() { cout << "in fun1 " <<a << endl; return a; } int main() { //當左值 fun1() = 100; cout << "in fun2 " << a<< endl; //當右值 int a = fun1(); return 0; } chunli@Linux:~/c++$ g++ main.cpp && ./a.out in fun1 20 in fun2 100 in fun1 100
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。