(建立于2017/12/20)
1.命名空間
namespace :C++引入的用于解決多個子產品間命名沖突問題的一個機制,他是一個由程式設計者命名的記憶體區域,程式設計者可以根據需要指定一些有名字的空間域,把一些全局實體分别放在各個命名空間中,進而與其他全局實體分隔開來。
#include <stdlib.h>
#include<iostream>
//标準命名空間(包含很多标準的定義)
//命名空間類似于Java中的包
using namespace std;
//自定義命名空間
namespace NSP_A {
int a = 9;
struct Teacher
{
char name[29];
int age;
};
struct Student
{
char name[29];
int age;
};
}
namespace NSP_B {
int a = 12;
//命名空間嵌套
namespace NSP_C {
int c = 90;
}
struct Teacher
{
char name[29];
int age;
};
struct Student
{
char name[29];
int age;
};
}
void main() {
//<<運算符重載
//std::cout << "this is a c ++" << std::endl;
//上邊一行可以寫成下邊的樣子,不過需要添加 using namespace std;
cout << "this is a c++" << endl;
//使用命名空間
//::通路修飾符
cout << NSP_A::a << endl;
cout << NSP_B::a << endl;
//通路命名空間中的命名空間的值
cout << NSP_B::NSP_C::c << endl;
//通路命名空間中的結構體(struct寫與不寫都可以)
//struct NSP_A::Teacher t;
//t.age = 123;
//struct NSP_A::Student s;
//s.age = 12;
//上邊四行可以寫作這種形式
using namespace NSP_A;
Teacher t;
t.age = 123;
Student s;
s.age = 12;
cout << t.age << endl;
cout << s.age << endl;
//如果多個命名空間中有相同的比如說結構體,我們需要每個都通路到(似乎會包重複的問題)
//嚴重性 代碼 說明 項目 檔案 行 禁止顯示狀态
//錯誤 C2086 “NSP_A::Student s” : 重定義 C++_study c : \users\renzhenming\documents\visual studio 2015\projects\c++_study\c++_study\1.cpp 75
//Student s;
//s.age = 300;
//cout << s.age << endl;
using NSP_B::Student;
Student s1;
s1.age = 200;
cout << s1.age << endl;
system("pause");
}
輸出結果:
this is a c++
9
12
90
123
12
200
請按任意鍵繼續. . .
(2018年7月29日補充)
2.第一個c++程式
#include "iostream" //包含c++的頭檔案
//使用std标準命名空間,在這個空間中定義了很多标準定義
using namespace std;
void main() {
//輸出到螢幕
cout << "hello world" << endl;
system("pause");
}
2.以面向過程的方式求圓的面積
#include "iostream" //包含c++的頭檔案
//使用std标準命名空間,在這個空間中定義了很多标準定義
using namespace std;
void main() {
double r = 0;
double s = 0;
cout << "請輸入圓的半徑" << endl;
//cin标準輸入,表示鍵盤
cin >> r;
cout <<"半徑的值是:"<<r << endl;
s = 3.14*r*r;
//輸出到螢幕
cout << "圓的面積是s:"<<s << endl;
system("pause");
}
3.以面向對象的方式求圓的面積
C++雖然是基于c語言,但是二者有本質不同,C++是面向對象程式設計,C語言是面向過程程式設計,學習c++要首先進行思想的轉變,對于由Java基礎的同學來說,這一點了解起來會比較容易,既然以面向對象的方式解決這個需求,那麼很明顯,圓就是我們要處理的這個對象
#include "iostream" //包含c++的頭檔案
//使用std标準命名空間,在這個空間中定義了很多标準定義
using namespace std;
//在c++中定義了一個自定義資料類型Circle
class Circle
{
//成員變量 public類型的
public:
double m_s; //面積
double m_r; //半徑
//成員函數,public類型
public:
void setR(double r) {
m_r = r;
}
double getR() {
return m_r;
}
double getS() {
m_s = 3.14*m_r*m_r;
return m_s;
}
};
void main() {
//用類定義三個對象
Circle c1, c2, c3;
double r;
cout << "請輸入半徑:"<< endl;
cin >> r;
c1.setR(r);
cout << "圓的面積是s:"<<c1.getS()<< endl;
system("pause");
}
類是一個資料類型(固定大小記憶體塊的别名),定義一個類,是一個抽象的概念,此時不會配置設定記憶體,隻有在用資料類型定義變量的時候才會配置設定記憶體。上邊的代碼中使用一個資料類型定義了三個變量c1 c2 c3,那麼在c1調用類方法的時候,編譯器是如何區分c1 c2 c3的呢?
3.C++對C的擴充
a.namespace命名空間
b.實用性加強
在早期C語言編譯器中,變量必須在使用域開始的地方定義,否則編譯無法通過,如下這種方式是錯誤的,因為在列印語句之後又定義了一個變量b,正确的寫法是先定義在列印。不過c++改變了這種情況,在c++中隻要在使用前定義即可,位置沒有要求
#include <stdio.h>
int main() {
int a=1;
printf("%d\n", a);
int b = 2;
printf("%d\n", b);
system("pause");
return 0;
}
c.變量檢測
C語言中,重複定義的同名全局變量是合法的,多個全局變量會被連結到全局資料區的同一個位址空間
int a;
int a = 1;
在c++中,拒絕這種二次定義的形式,編譯無法通過
d.struct類型加強
1.c語言的struct定義了一組變量的集合,c編譯器并不認為這是一種新的類型,c++的struct是一個新類型的定義聲明。什麼意思?看下邊這種使用結構體的方式在C語言編譯器是無法編譯通過的,定義結構體變量要前邊加struct關鍵字。但是在c++編譯器是可以的
2.另外,c++中,結構體内的變量也可以使用權限修飾符public protected等
3.c++中的結構體可以和class完成相同的功能
#include <stdio.h>
struct Me {
int a;
};
int main() {
Me me1; //struct Me me1;
me1.a = 10;
printf("%d\n", me1.a);
system("pause");
return 0;
}
#include "iostream" //包含c++的頭檔案
//使用std标準命名空間,在這個空間中定義了很多标準定義
using namespace std;
#include <stdio.h>
struct Me {
public:
int a;
protected:
int b;
};
int main() {
Me me1;
me1.a = 10;
printf("%d\n", me1.a);
system("pause");
return 0;
}
e.register關鍵字增強
register關鍵字請求編譯器将局部變量存儲在寄存器中,使用register修飾變量,暗示編譯程式相應的變量将被頻繁的使用,應盡可能(不是絕對的,是在寄存器空閑的狀态下有效)的将它儲存在寄存器中,以加快存儲速度。在C語言中register關鍵字定義的變量無法取位址,并且隻有手動加上register關鍵字的變量才會有可能被優化。c++中也支援register關鍵字,不過c++有自己的優化方式,不使用register關鍵字也可以根據情況自動判斷是否需要對代碼進行優化,c++可以取得register變量的位址。
f.c++中所有變量和函數都必須有類型
C語言中預設類型在c++中是不合法的
g.新增bool類型
bool可取值隻有true false,理論上隻占一個位元組,true代表真值,編譯器内部用1表示,false表示非真,編譯器内部用0表示
h.C++和C語言的三目運算符
C語言傳回變量的值,C++傳回變量的本身
C語言中的三目運算符傳回的是變量值,不能做左值使用,C++中的三目運算符可直接傳回變量本身,是以可以出現在程式任何地方
如下是在C語言中,編譯器直接提示表達式必須是可修改的左值,因為C語言三目運算符傳回的是變量的值,那麼因為a小于b,是以傳回a的值,a的值是10,然後将30指派給10,這是錯誤的。常量無法被修改
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
(a < b ? a : b) = 30;
system("pause");
return 0;
}
在C++中會怎樣呢?
#include "iostream" //包含c++的頭檔案
using namespace std;
int main() {
int a = 10;
int b = 20;
(a < b ? a : b) = 30;
cout << a<< endl;
system("pause");
return 0;
}
可以發現編譯通過并且列印a的值為30,因為C++三目運算符傳回的是變量本身,相當于多了一步取位址的操作,然後直接操作a指向的記憶體空間
C語言如何實作這種效果?隻需要稍作改動,其實c++中編譯器相當于幫我們做了這一步
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
*(a < b ? &a : &b) = 30;
printf("a=%d\n", a);
system("pause");
return 0;
}
i.C和C++中的const
const的作用是為了防止變量被修改,但實際上在C語言中,const是有缺陷的
C語言代碼,可以發現通過指針修改了const變量a
#include <stdio.h>
int main() {
const int a = 10;
int *p = &a;
printf("*p=%d\n", *p);
printf("a=%d\n", a);
system("pause");
return 0;
}
在c++中,這段代碼無法編譯通過,測試使用的編譯器是Visual Studio2015,可能在早期的版本上編譯可以通過,但是運作無法修改const常量值。c++編譯器是怎麼做到的?相對于C語言,c++編譯器會将const變量存入符号表中,當你要使用這個變量的時候在符号表中取出,而當你通過取位址的方式指派給一個指針的時候,編譯器會在記憶體中拷貝一份這個變量,是以你同過指針修改的變量跟符号表中的這個變量并沒有關系,進而保證const變量不被修改
//嚴重性 代碼 說明 項目 檔案 行 禁止顯示狀态
//錯誤 C2440 “初始化”: 無法從“const int *”轉換為“int *” Project8 c:\users\renzhenming
//documents\visual studio 2015\projects\project8\project8\a.cpp 5
//錯誤(活動) "const int *" 類型的值不能用于初始化 "int *" 類型的實體 Project8 //c:\Users\renzhenming\Documents\Visual Studio 2015\Projects\Project8\Project8\a.cpp
//5
#include "iostream" //包含c++的頭檔案
using namespace std;
int main() {
const int a = 10;
int *p = &a;
cout << "*p=%d\n"<<*p << endl;
cout << "a=%d\n"<<a << endl;
system("pause");
return 0;
}
const變量差別
C語言中const變量
是隻讀變量,有自己的存儲空間
c++中的const常量
可能配置設定空間,也可能不配置設定
當const常量為全局,并且需要在其他檔案中使用,會配置設定空間
當使用&操作符,取const常量位址時,會配置設定空間
當const int &a = 10; const修飾引用時,也會配置設定空間