① 關於c++的編程
#include<iostream>
using namespace std;
struct STU{
char name[20];
int age,score;
};
void input(STU *s,int n){
int i;
for(i=0; i<n; i++){
cout <<"輸入第 "<<i+1 <<" 個學生的姓名 年齡(16-28) 五分製成績(0-5):";
cin >>s[i].name >>s[i].age >>s[i].score;
if(s[i].age <16 || s[i].age>28)
throw 1;
if(s[i].score <0 || s[i].score>5)
throw 2;
}
}
void main(){
STU s[3];
try{
input(s, 3);
cout <<"姓名\t年齡\t百分製成績\n";
for(int i=0; i<3; i++){
cout <<s[i].name <<"\t" <<s[i].age <<"\t" <<s[i].score*20 <<endl;
}
}
catch(int e){
if(e==1)
cout <<"輸入錯誤:年齡超出范圍。\n";
if(e==2)
cout <<"輸入錯誤:成績超出范圍。\n";
}
catch(...){
cout <<"其它異常。\n";
}
}
② 為什麼非final方法不能進行inline優化
··inline是在編譯的時候直接調用函數代碼替換。
所以不用在運行的時候調用函數而因此優化。
所以inline需要在編譯的時候就知道最後要用哪個函數。
顯然,非final是不行的,因為在編譯的時候不能知道。
而多態能知道運行的實際是哪個函數,那是在運行的時候才能知道,
運行時在編譯之後。
一個代碼編譯通過但是不一定能運行,但是不能編譯一定運行不了,這說明運行在編譯之後。
③ 內聯函數需要用inline關鍵字聲明嗎
要寫!但注意的是當你的函數不符合內聯函數的規則時,系統自動會把內聯函數當做一半函數類處理!
④ inline和virtual沖突嗎
其實內聯函數和虛函數並不是沖突的,而是內聯函數和使用虛機制調用的虛函數是沖突的.也就是說,虛函數可以靜態調用也可以通過虛機制動態調用,所以如果虛函數通過靜態調用的話就和內聯函數是不沖突的.
總結:inline和virtual這兩個標識符不是沖突的,而是在底層實現上存在沖突
⑤ C++ inline函數為什麼不能繼承
inline成員函數可以繼承。
inline和類繼承並沒有關系。另外在類中直接定義函數體的成員函數默認就是inline的:
structA
{
intfoo()//這里等價於寫inlineintfoo(),並且這個foo顯然是可以繼承的
{
return0;
}
};
因為inline函數另一個特性就是可以在不同編譯單元里重復定義,而把成員函數體定義寫在類定義裡面會導致所有用這個類的編譯單元都必須有函數體的定義,所以必須作為inline函數存在。
⑥ 為什麼虛函數不應該是內聯(inline)函數
常見的不能聲明為虛函數的有:普通函數(非成員函數)、靜態成員函數、內聯成員函數、構造函數、友元函數。1、為什麼C++不支持普通函數為虛函數? 普通函數(非成員函數)只能overload,不能被override,聲明為虛函數也沒有什麼意思,因此編譯器會在編譯時綁定函數。2、為什麼C++不支持構造函數為虛函數?這個原因很簡單,主要是從語義上考慮,所以不支持。因為構造函數本來是為了明確初始化對象成員才產生的,然而virtual function主要是為了在不完全了解細節的情況下也能正確處理對象。另外,虛函數是在不同類型的對象產生不同的動作,現在對象還沒有產生,如何使用虛函數來完成你想完成的動作。3、為什麼C++不支持靜態成員函數為虛函數? 靜態成員函數對於每個類來說只有一份代碼,所有的對象都共享這一份代碼,他不歸某個對象所有,所以他也沒有動態綁定的必要性。4、為什麼C++不支持內聯成員函數為虛函數? 其實很簡單,內聯函數就是為了在代碼中直接展開,減少函數調用話費的代價,虛函數是為了在繼承後對象能夠准確的執行自己的動作,這是不可能統一的。再說,inline函數在編譯時被展開,虛函數在運行時才能動態的綁定函數。5、為什麼C++不支持友元函數為虛函數?
⑦ C++中哪些函數不能聲明為inline
內有虛函數調用的是不可以的,因為inline要求編譯期展開,虛函數則是運行時確認,如果函數比較復雜,內有遞歸和循環,編譯器也許會忽略inline請求。
⑧ 關於C++中虛函數的疑問
內聯函數用關鍵是inline,這個關鍵字只是表示 一個要求,編譯器並不承諾將inline修飾的函數作為內聯函數。內聯函數在編譯時將函數體嵌入在每一個調用處。也就是說將一些功能簡單規模小又使用頻繁的函數設計為內聯函數能節省開銷,但是你將一個復雜的函數設置為內聯函數的話編譯器會自動將其轉換為普通函數。
至於「內聯函數不能聲明為虛函數」,看下面代碼:
class A
{
vritual void fun();//虛函數,實現代碼略
};
class B:public A
{
void fun();//實現代碼略
};
void main()
{
B b;
A * p;
p =& b;
p->fun();
}
在main函數里,如果基類沒有將fun()聲明為虛函數,則p->fun()根據指針類型(A * p)調用A::fun(),這個指針是編譯的時候就知道的,編譯器在進行編譯的時候將fun()關聯到A::fun(),這屬於靜態聯編;
但是如果基類A將fun()函數聲明為虛函數,則p->fun();將根據對象類型調用(B)調用B::fun(),上面的代碼中對象是b,通常只有在運行的時候才能確定對象的類型,運行時候將根據對象類型將fun()關聯到A::fun()或者B::fun(),這個屬於動態聯編。
這個就容易理解「內聯函數不能聲明為虛函數」,當虛函數是動態聯編的時候編譯器無法確定對象類型從而無法將函數體嵌入在每一個調用處。
這么解釋能理解了嗎?多看幾遍你的教材裡面相關概念再結合教材關於虛函數聯編的例子就很好理解了。
⑨ 什麼函數不能聲明為虛函數
inline, static, constructor ,template 函數都不能 為虛函數,而析構函數可以。
為什麼呢:
inline: 編譯器替換; 而虛函數是為了解決運行期間綁定。
static:class 成員; 編譯期間就給class了。
constructor: 構造函數表示要生成一個class的object;假設是virtual的,那就說不知道這個實例化derived還是based的class。但是類型實例化必須在編譯期確定(否則編譯器不知道到底是什麼對象了)
template:模板實例是在 compile-time,virtual就意味著在run-time確定。這讓編譯器設計者為難了,這就是說虛函數表要指向各種版本的 template function 實例,代碼設計者confuse,編譯器設計者也覺得蠻煩。
⑩ C++編譯器(Dev-C)是否會自動內聯函數 對於什麼樣的函數即使標記inline也會拒絕內聯
G++編譯器是否會自動進行內聯函數?
G++編譯器是很先進的,編譯的時候如果開啟優化,G++會代碼進行各種優化,如:對合適的函數進行內聯(即便是沒有添加inline關鍵字),對某些函數直接對其進行求值,除此之外G++編譯器還可以對代碼進行重排序 等等。編譯器比你更了解硬體,所以只要允許它優化,他會盡量進行優化。你使用的Dev C++集成開發環境使用的c++編譯器就是G++。
什麼樣的函數即使標記inline也無法內聯?
比如函數體太大、太復雜的話(比如包含多重循環、包含遞歸調用),對其進行內聯得不償失,這時編譯器就會忽略inline關鍵字,VC++編譯器提供了強制內聯函數的關鍵字,除非你非常了解硬體,不然最好讓編譯器來處。編譯不對那些函數進行內聯要看具體的編譯器實現了。
inline關鍵字的有哪些作用?
inline關鍵字可以提示編譯器對某個函數進行內聯,並且強制函數使用內部鏈接。比如說你在頭文件定義了某個函數,為了防止多重定義,你可以添加inline關鍵字來防止多重定義錯誤。
如果對硬體不是很了解,底層的代碼優化還是留給編譯器來處理。
看看下面的幾個編譯器優化函數的例子:
1.編譯器直接對函數求值:
解釋一下:
第一條和第二天指令分別將b和a的地址載入到寄存器rdx和rcx中
第三條指令將b的值載入到eax寄存器中
第四條指令將34存入b中
第五條指令將eax的值加1(eax保存了之前b的值)
第六條指令將eax的值存入a中
可以看出編譯器將函數的兩條語句換了位置,這種優化主要是優化代碼的執行速度,有的CPU內存讀寫操作的的開銷不一樣,所以重新排序一下某些代碼能夠提高程序執行速度。