我的評論
re: Java異常處理之陋習展播(轉) 噼里啪啦的世界 2005-04-20 10:24
我是看到了。。。
re: 哈哈...今天看到4-16游行隊伍的照片,在其中竟然發現我啦,有意義哦~~~ 噼里啪啦的世界 2005-04-20 10:21
怎么就兩張。。我看到我了 就是沒有臉了 哈哈
re: 禽獸!我等著你! 噼里啪啦的世界 2005-04-20 10:20
這是什么咚咚!!
re: sql 擴展 噼里啪啦的世界 2005-04-08 09:23
SQL 流程控制命令
作者:unknown 更新時間:2005-03-17
Transact-SQL 語言使用的流程控制命令與常見的程序設計語言類似主要有以下幾種控制命令。
4.6.1 IF…ELSE
其語法如下:
IF <條件表達式>
<命令行或程序塊>
[ELSE [條件表達式]
<命令行或程序塊>]
其中<條件表達式>可以是各種表達式的組合,但表達式的值必須是邏輯值“真”或“假”。ELSE子句是可選的,最簡單的IF語句沒有ELSE子句部分。IF…ELSE用來判斷當某一條件成立時執行某段程序,條件不成立時執行另一段程序。如果不使用程序塊,IF或ELSE只能執行一條命令。IF…ELSE可以進行嵌套。
例4-9
declare@x int,@y int,@z int
select @x=1,@y=2, @z=3
if@x>@y
print'x>y' --打印字符串'x>y'
else if@y>@z
print'y>z'
else print'z>y'
運行結果如下
z>y
注意:在Transact-SQL中最多可嵌套32級。
4.6.2 BEGIN…END
其語法如下:
BEGIN
<命令行或程序塊>
END
BEGIN…END用來設定一個程序塊,將在BEGIN…END內的所有程序視為一個單元執行BEGIN…END經常在條件語句,如IF…ELSE中使用。在BEGIN…END中可嵌套另外的BEGIN…END來定義另一程序塊。
4.6.3 CASE
CASE 命令有兩種語句格式:
CASE <運算式>
WHEN <運算式>THEN<運算式>
…
WHEN<運算式>THEN<運算式>
[ELSE<運算式>]
END
CASE
WHEN <條件表達式> THEN <運算式>
WHEN <條件表達式> THEN <運算式>
[ELSE <運算式>]
END
CASE命令可以嵌套到SQL命令中。
例4-10:調整員工工資,工作級別為“1”的上調8%,工作級別為“2”的上調7%,工作級別為“3”的上調6%,其它上調5%。
use pangu
update employee
set e_wage =
case
when job_level = ’1’ then e_wage*1.08
when job_level = ’2’ then e_wage*1.07
when job_level = ’3’ then e_wage*1.06
else e_wage*1.05
end
注意:執行CASE子句時,只運行第一個匹配的子名。
4.6.4 WHILE…CONTINUE…BREAK
其語法如下:
WHILE <條件表達式>
BEGIN
<命令行或程序塊>
[BREAK]
[CONTINUE]
[命令行或程序塊]
END
WHILE 命令在設定的條件成立時會重復執行命令行或程序塊。CONTINUE命令可以讓程序跳過CONTINUE 命令之后的語句,回到WHILE 循環的第一行命令。BREAK 命令則讓程序完全跳出循環,結束WHILE 命令的執行。WHILE 語句也可以嵌套。
例4-11:
declare @x int @y int @c int
例4-11:
declare @x int, @y int, @c int
select @x = 1, @y=1
while @x < 3
begin
print @x --打印變量x 的值
while @y < 3
begin
select @c = 100*@ x+ @y
print @c --打印變量c 的值
select @y = @y + 1
end
select @x = @x + 1
select @y = 1
end
運行結果如下
1
101
102
2
201
202
4.6.5 WAITFOR
其語法如下:
WAITFOR {DELAY <‘時間’> | TIME <‘時間’>
| ERROREXIT | PROCESSEXIT | MIRROREXIT}
WAITFOR 命令用來暫時停止程序執行,直到所設定的等待時間已過或所設定的時間已到才繼續往下執行。其中‘時間’必須為DATETIME 類型的數據,如:‘11:15:27’,
但不能包括日期各關鍵字含義如下:
DELAY 用來設定等待的時間最多可達24 小時;
TIME 用來設定等待結束的時間點;
ERROREXIT 直到處理非正常中斷;
PROCESSEXIT 直到處理正?;蚍钦V袛?;
MIRROREXIT 直到鏡像設備失敗。
例4-12 等待1 小時2 分零3 秒后才執行SELECT 語句
waitfor delay ’01:02:03’
select * from employee
例4-13:等到晚上11 點零8 分后才執行SELECT 語句
waitfor time ’23:08:00’
select * from employee
4.6.6 GOTO
語法如下:
GOTO 標識符
GOTO 命令用來改變程序執行的流程,使程序跳到標有標識符的指定的程序行再繼續往下執行。作為跳轉目標的標識符可為數字與字符的組合,但必須以“:”結尾,如‘12:’或‘a_1:’。在GOTO 命令行,標識符后不必跟“:”。
例4-14 分行打印字符‘1’、‘2’、‘3’、‘4’、‘5’
declare @x int
select @x = 1
label_1
print @x
select @x = @x + 1
while @x < 6
goto label_1
4.6.7 RETURN
語法如下
RETURN [整數值]
RETURN 命令用于結束當前程序的執行,返回到上一個調用它的程序或其它程序。在括號內可指定一個返回值。
例4-15
declare @x int @y int
select @x = 1 @y = 2
if x>y
return 1
else
return 2
如果沒有指定返回值,SQL Server 系統會根據程序執行的結果返回一個內定值,如
表4-5 所示。
如果運行過程產生了多個錯誤,SQL Server系統將返回絕對值最大的數值;如果此時用戶此時定義了返回值,則以返回用戶定義的值。RETURN語句不能返回NULL值。
作者:unknown 更新時間:2005-03-17
Transact-SQL 語言使用的流程控制命令與常見的程序設計語言類似主要有以下幾種控制命令。
4.6.1 IF…ELSE
其語法如下:
IF <條件表達式>
<命令行或程序塊>
[ELSE [條件表達式]
<命令行或程序塊>]
其中<條件表達式>可以是各種表達式的組合,但表達式的值必須是邏輯值“真”或“假”。ELSE子句是可選的,最簡單的IF語句沒有ELSE子句部分。IF…ELSE用來判斷當某一條件成立時執行某段程序,條件不成立時執行另一段程序。如果不使用程序塊,IF或ELSE只能執行一條命令。IF…ELSE可以進行嵌套。
例4-9
declare@x int,@y int,@z int
select @x=1,@y=2, @z=3
if@x>@y
print'x>y' --打印字符串'x>y'
else if@y>@z
print'y>z'
else print'z>y'
運行結果如下
z>y
注意:在Transact-SQL中最多可嵌套32級。
4.6.2 BEGIN…END
其語法如下:
BEGIN
<命令行或程序塊>
END
BEGIN…END用來設定一個程序塊,將在BEGIN…END內的所有程序視為一個單元執行BEGIN…END經常在條件語句,如IF…ELSE中使用。在BEGIN…END中可嵌套另外的BEGIN…END來定義另一程序塊。
4.6.3 CASE
CASE 命令有兩種語句格式:
CASE <運算式>
WHEN <運算式>THEN<運算式>
…
WHEN<運算式>THEN<運算式>
[ELSE<運算式>]
END
CASE
WHEN <條件表達式> THEN <運算式>
WHEN <條件表達式> THEN <運算式>
[ELSE <運算式>]
END
CASE命令可以嵌套到SQL命令中。
例4-10:調整員工工資,工作級別為“1”的上調8%,工作級別為“2”的上調7%,工作級別為“3”的上調6%,其它上調5%。
use pangu
update employee
set e_wage =
case
when job_level = ’1’ then e_wage*1.08
when job_level = ’2’ then e_wage*1.07
when job_level = ’3’ then e_wage*1.06
else e_wage*1.05
end
注意:執行CASE子句時,只運行第一個匹配的子名。
4.6.4 WHILE…CONTINUE…BREAK
其語法如下:
WHILE <條件表達式>
BEGIN
<命令行或程序塊>
[BREAK]
[CONTINUE]
[命令行或程序塊]
END
WHILE 命令在設定的條件成立時會重復執行命令行或程序塊。CONTINUE命令可以讓程序跳過CONTINUE 命令之后的語句,回到WHILE 循環的第一行命令。BREAK 命令則讓程序完全跳出循環,結束WHILE 命令的執行。WHILE 語句也可以嵌套。
例4-11:
declare @x int @y int @c int
例4-11:
declare @x int, @y int, @c int
select @x = 1, @y=1
while @x < 3
begin
print @x --打印變量x 的值
while @y < 3
begin
select @c = 100*@ x+ @y
print @c --打印變量c 的值
select @y = @y + 1
end
select @x = @x + 1
select @y = 1
end
運行結果如下
1
101
102
2
201
202
4.6.5 WAITFOR
其語法如下:
WAITFOR {DELAY <‘時間’> | TIME <‘時間’>
| ERROREXIT | PROCESSEXIT | MIRROREXIT}
WAITFOR 命令用來暫時停止程序執行,直到所設定的等待時間已過或所設定的時間已到才繼續往下執行。其中‘時間’必須為DATETIME 類型的數據,如:‘11:15:27’,
但不能包括日期各關鍵字含義如下:
DELAY 用來設定等待的時間最多可達24 小時;
TIME 用來設定等待結束的時間點;
ERROREXIT 直到處理非正常中斷;
PROCESSEXIT 直到處理正?;蚍钦V袛?;
MIRROREXIT 直到鏡像設備失敗。
例4-12 等待1 小時2 分零3 秒后才執行SELECT 語句
waitfor delay ’01:02:03’
select * from employee
例4-13:等到晚上11 點零8 分后才執行SELECT 語句
waitfor time ’23:08:00’
select * from employee
4.6.6 GOTO
語法如下:
GOTO 標識符
GOTO 命令用來改變程序執行的流程,使程序跳到標有標識符的指定的程序行再繼續往下執行。作為跳轉目標的標識符可為數字與字符的組合,但必須以“:”結尾,如‘12:’或‘a_1:’。在GOTO 命令行,標識符后不必跟“:”。
例4-14 分行打印字符‘1’、‘2’、‘3’、‘4’、‘5’
declare @x int
select @x = 1
label_1
print @x
select @x = @x + 1
while @x < 6
goto label_1
4.6.7 RETURN
語法如下
RETURN [整數值]
RETURN 命令用于結束當前程序的執行,返回到上一個調用它的程序或其它程序。在括號內可指定一個返回值。
例4-15
declare @x int @y int
select @x = 1 @y = 2
if x>y
return 1
else
return 2
如果沒有指定返回值,SQL Server 系統會根據程序執行的結果返回一個內定值,如
表4-5 所示。
如果運行過程產生了多個錯誤,SQL Server系統將返回絕對值最大的數值;如果此時用戶此時定義了返回值,則以返回用戶定義的值。RETURN語句不能返回NULL值。
re: 我的java學習筆記(第一章 回顧C/C++ 基本概念) 噼里啪啦的世界 2005-04-01 06:53
const主要是為了程序的健壯型,減少程序出錯.
最基本的用法:
const int a=100; b的內容不變,b只能是100也就是聲明一個int類型的常量(#define b =100)
int const b=100; //和上面作用一樣
const指針和引用一般用在函數的參數中
int* m = &a; //出錯,常量只能用常指針
int c= 1;const int*pc = &c;//常指針可指向常量
const int* pa = &a; //指針指向的內容為常量(就是b的值不變)
int const *a = &b; //指針指向的內容為常量(就是b的值不變)*p=3//error
int* const a = &b; //指針為常量,不能更改指針了如 a++但可以改值*p=3;
從這可以看出const放在*左側修飾的是指針的內容,const放在*右側修飾的是指針
本身.
const引用的用法和指針一樣
int const & a=b; 和指針一樣
const int& a=b; 和指針一樣
但沒有 int& const a=b 的用法因為引用不能做移位運算,但只是出個warning
const int* const a = &b; //綜合應用,一般用來傳遞多維的數組
類如:char* init[] = {"Paris","in the","Spring"};
void fun(const int* const a){}
fun(init)//保護參數不被修改
int A(int)const; //是常函數,只能用在類中,調用它的對象不能改改變成員值
const int A(); //返回的是常量,所以必須這么調用 cosnt int a=A();
int A(const int); //參數不能改值,可用在任意函數
int A(const int*);
....
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
const int* pHeap = new int;
delete pHeap;
p = NULL;//出錯
我的解決辦法是強制類型轉換
const int* pHeap = new int(1);
delete (int*)pHeap;
pHeap = NULL;
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
目前我就遇到這些問題,那位還有補充的嗎
能不能把自己的經驗也談談。大家交流交流
這個就是我在調錯時發現的
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
Thinking again in C++(一)常量性原理 cphj(原作)
有些地方很受啟發
1.不能將const修飾的任何對象、引用和指針作為賦值表達式的左值。
const int cx=100;
const int & rcx=cx;
const int * pcx=&cx;
cx=200; //error
rcx=200; //error
*pcx=200; //error
2.const類型的對象不能直接被non-const類型的別名所引用。
(1)不能將const類型的對象傳遞給non-const類型的引用。
const int cx=100;
int & rx=cx; //error
(2)不能將const類型的實參傳遞給形參為non-const類型引用的函數。
void f(int a)
{
}
void g(int & ra)
{
}
const int cx=100;
f(cx); //ok
g(cx); //error
(3)不能將const類型的對象作為non-const類型引用的函數返回值。
int & f(const int & rca)
{
return rca; //error
}
int x=100;
f(x);
3.可以使用const類型別名引用non-const對象。此時通過const引用不能修改對象,但對象可以通過non-const引用被修改。
int x=100;
int & rx=x;
const int & rcx=x; //ok
x=200;
rx=200;
rcx=200; //error
4.指針的屬性有兩個:指針的類型和指針本身的常量性。其中,指向const對象與指向non-const對象,是不同的指針類型。
int x=100;
const int * pcx=&x; //[1]
int * px=&x; //[2]
int y=100;
int * const cpy=&y; //[3]
int * py=&y; //[4]
[1][2]兩個指針的類型不同;[3][4]兩個指針的常量性不同。
對象與指向對象的指針的規則類似于對象與引用。即,const類型的對象不能直接被non-const類型的指針所指示(同2);可以使用const類型的指針指向non-const對象(同3)。
5.可以將相同類型(包括常量性)的const指針值賦給non-const指針。
int x=100;
int * px;
const int * pcx=&x;
px=pcx; //error
int * const cpx=&x;
px=cpx; //ok
6.若函數的返回值為內建類型或是指針,則該返回值自動成為const性質。但自定義類型則為non-const性質。
int f() //相當于返回const int
{
return 100;
}
int * g(int & ra) //相當于返回int * const
{
return &ra;
}
class CTest
{
int n;
public:
CTest(int n){this->n=n;}
};
CTest h() //返回的就是CTest
{
return CTest(200);
}
f()=200; //error
int x=100;
int y=200;
int * px=&x;
g(y)=px; //error
*g(y)=x; //ok,從這點可以看出g()返回的不是const int *
CTest t(100);
h()=t; //ok,但卻是完全錯誤的、危險的做法
//所以h()的正確寫法是返回const CTest
const int b=100; b的內容不變,b只能是100
int const b=100; b必須為int型,不能為其他類型?
這2句話的意思應該是一樣的吧 , THINKING IN C++是這樣說的
const int a=100; a的內容不變,a只能是100(同樣不能類型轉換)。
int const b=100; b必須為int型,不能為其他類型?(同樣在使用中不能修改)。
所以a和b是一樣的,稱為整型常數,在使用中不能被修改,當然都不能轉為其他類型了。
#include <iostream>
using namespace std;
int main()
{
const int a = 100;
int const b = 100;
a = 100; //這四條語句編譯時都會出現“Cannot modify a const object
b = 100; //in function main()”的錯誤提示,也就是說,任何企圖修改 a = 100.0; //a和b(其實是一樣的)的行為都會出現“災難”,在語法上講就 b = 100.0; //是a和b都不能出現在賦值語句的左邊!
cout<<'\n'<<a<<'\n'<<b<<endl;
return 0;
}
常函數的調用是這樣的:常量對象只能調用常成員函數,非常量對象即可以調常成員函數,也可以調一般成員函數,但當某個函數有const和非const兩個版本時,const對象調const版本,非const對象調非const版本
例:
class A
{
public:
int & GetData(){return data;}
const int & GetData()const {return data;}
private:
int data;
}
A a;
a.GetData();//調用int & GetData(){return data;}
//但如果沒有這個函數,也可以調用const int & GetData()const
const A const_a;
const_a.GetData();//調用const int & GetData()const {return data;}
常函數只能調常函數,也是由于這個原因
算你狠!加兩點
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
#include <iostream.h>
void fun(char b){cout <<"void"<<endl;}
int fun(int const b){cout <<"int"<<endl;}
int main()
{
fun(1.0);//詳細看看重載函數吧
fun(4); //想一想調用哪一個
return 0;
}
我試了一下,會出錯? vc說:'fun':ambiguous call to overloaded function
補充的好啊,這個一般不會注意的
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
這個可真有意思,調試時兩個都是2,可編譯就是2,1了
const的永遠都是const,這樣能更改就不錯了,不然就自相矛盾了
奇怪的是 pi 和 &i地址一樣啊,就像樓上說的這是編譯時的優化
處理
const int i = 1;
int* pi=const_cast<int*>(&i);
*pi=2;
cout << *pi << endl;
cout << i << endl;
那個主要是隱式轉換
你可依次把兩個函數注掉看看調用
#include <iostream.h>
//void fun(char b){cout <<"void"<<endl;}
void fun(int b){cout <<"int"<<endl;}
int main()
{
fun('a');
fun(4);
return 0;
}
最基本的用法:
const int a=100; b的內容不變,b只能是100也就是聲明一個int類型的常量(#define b =100)
int const b=100; //和上面作用一樣
const指針和引用一般用在函數的參數中
int* m = &a; //出錯,常量只能用常指針
int c= 1;const int*pc = &c;//常指針可指向常量
const int* pa = &a; //指針指向的內容為常量(就是b的值不變)
int const *a = &b; //指針指向的內容為常量(就是b的值不變)*p=3//error
int* const a = &b; //指針為常量,不能更改指針了如 a++但可以改值*p=3;
從這可以看出const放在*左側修飾的是指針的內容,const放在*右側修飾的是指針
本身.
const引用的用法和指針一樣
int const & a=b; 和指針一樣
const int& a=b; 和指針一樣
但沒有 int& const a=b 的用法因為引用不能做移位運算,但只是出個warning
const int* const a = &b; //綜合應用,一般用來傳遞多維的數組
類如:char* init[] = {"Paris","in the","Spring"};
void fun(const int* const a){}
fun(init)//保護參數不被修改
int A(int)const; //是常函數,只能用在類中,調用它的對象不能改改變成員值
const int A(); //返回的是常量,所以必須這么調用 cosnt int a=A();
int A(const int); //參數不能改值,可用在任意函數
int A(const int*);
....
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
const int* pHeap = new int;
delete pHeap;
p = NULL;//出錯
我的解決辦法是強制類型轉換
const int* pHeap = new int(1);
delete (int*)pHeap;
pHeap = NULL;
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
目前我就遇到這些問題,那位還有補充的嗎
能不能把自己的經驗也談談。大家交流交流
這個就是我在調錯時發現的
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
Thinking again in C++(一)常量性原理 cphj(原作)
有些地方很受啟發
1.不能將const修飾的任何對象、引用和指針作為賦值表達式的左值。
const int cx=100;
const int & rcx=cx;
const int * pcx=&cx;
cx=200; //error
rcx=200; //error
*pcx=200; //error
2.const類型的對象不能直接被non-const類型的別名所引用。
(1)不能將const類型的對象傳遞給non-const類型的引用。
const int cx=100;
int & rx=cx; //error
(2)不能將const類型的實參傳遞給形參為non-const類型引用的函數。
void f(int a)
{
}
void g(int & ra)
{
}
const int cx=100;
f(cx); //ok
g(cx); //error
(3)不能將const類型的對象作為non-const類型引用的函數返回值。
int & f(const int & rca)
{
return rca; //error
}
int x=100;
f(x);
3.可以使用const類型別名引用non-const對象。此時通過const引用不能修改對象,但對象可以通過non-const引用被修改。
int x=100;
int & rx=x;
const int & rcx=x; //ok
x=200;
rx=200;
rcx=200; //error
4.指針的屬性有兩個:指針的類型和指針本身的常量性。其中,指向const對象與指向non-const對象,是不同的指針類型。
int x=100;
const int * pcx=&x; //[1]
int * px=&x; //[2]
int y=100;
int * const cpy=&y; //[3]
int * py=&y; //[4]
[1][2]兩個指針的類型不同;[3][4]兩個指針的常量性不同。
對象與指向對象的指針的規則類似于對象與引用。即,const類型的對象不能直接被non-const類型的指針所指示(同2);可以使用const類型的指針指向non-const對象(同3)。
5.可以將相同類型(包括常量性)的const指針值賦給non-const指針。
int x=100;
int * px;
const int * pcx=&x;
px=pcx; //error
int * const cpx=&x;
px=cpx; //ok
6.若函數的返回值為內建類型或是指針,則該返回值自動成為const性質。但自定義類型則為non-const性質。
int f() //相當于返回const int
{
return 100;
}
int * g(int & ra) //相當于返回int * const
{
return &ra;
}
class CTest
{
int n;
public:
CTest(int n){this->n=n;}
};
CTest h() //返回的就是CTest
{
return CTest(200);
}
f()=200; //error
int x=100;
int y=200;
int * px=&x;
g(y)=px; //error
*g(y)=x; //ok,從這點可以看出g()返回的不是const int *
CTest t(100);
h()=t; //ok,但卻是完全錯誤的、危險的做法
//所以h()的正確寫法是返回const CTest
const int b=100; b的內容不變,b只能是100
int const b=100; b必須為int型,不能為其他類型?
這2句話的意思應該是一樣的吧 , THINKING IN C++是這樣說的
const int a=100; a的內容不變,a只能是100(同樣不能類型轉換)。
int const b=100; b必須為int型,不能為其他類型?(同樣在使用中不能修改)。
所以a和b是一樣的,稱為整型常數,在使用中不能被修改,當然都不能轉為其他類型了。
#include <iostream>
using namespace std;
int main()
{
const int a = 100;
int const b = 100;
a = 100; //這四條語句編譯時都會出現“Cannot modify a const object
b = 100; //in function main()”的錯誤提示,也就是說,任何企圖修改 a = 100.0; //a和b(其實是一樣的)的行為都會出現“災難”,在語法上講就 b = 100.0; //是a和b都不能出現在賦值語句的左邊!
cout<<'\n'<<a<<'\n'<<b<<endl;
return 0;
}
常函數的調用是這樣的:常量對象只能調用常成員函數,非常量對象即可以調常成員函數,也可以調一般成員函數,但當某個函數有const和非const兩個版本時,const對象調const版本,非const對象調非const版本
例:
class A
{
public:
int & GetData(){return data;}
const int & GetData()const {return data;}
private:
int data;
}
A a;
a.GetData();//調用int & GetData(){return data;}
//但如果沒有這個函數,也可以調用const int & GetData()const
const A const_a;
const_a.GetData();//調用const int & GetData()const {return data;}
常函數只能調常函數,也是由于這個原因
算你狠!加兩點
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
#include <iostream.h>
void fun(char b){cout <<"void"<<endl;}
int fun(int const b){cout <<"int"<<endl;}
int main()
{
fun(1.0);//詳細看看重載函數吧
fun(4); //想一想調用哪一個
return 0;
}
我試了一下,會出錯? vc說:'fun':ambiguous call to overloaded function
補充的好啊,這個一般不會注意的
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
這個可真有意思,調試時兩個都是2,可編譯就是2,1了
const的永遠都是const,這樣能更改就不錯了,不然就自相矛盾了
奇怪的是 pi 和 &i地址一樣啊,就像樓上說的這是編譯時的優化
處理
const int i = 1;
int* pi=const_cast<int*>(&i);
*pi=2;
cout << *pi << endl;
cout << i << endl;
那個主要是隱式轉換
你可依次把兩個函數注掉看看調用
#include <iostream.h>
//void fun(char b){cout <<"void"<<endl;}
void fun(int b){cout <<"int"<<endl;}
int main()
{
fun('a');
fun(4);
return 0;
}
re: 我的java學習筆記(第一章 回顧C/C++ 基本概念) 噼里啪啦的世界 2005-04-01 06:52
常量定義規則
【規則5-3-1】需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部。為便于管理,可以把不同模塊的常量集中存放在一個公共的頭文件中。
【規則5-3-2】如果某一常量與其它常量密切相關,應在定義中包含這種關系,而不應給出一些孤立的值。
例如:
const float RADIUS = 100;
const float DIAMETER = RADIUS * 2;
類中的常量
有時我們希望某些常量只在類中有效。由于#define定義的宏常量是全局的,不能達到目的,于是想當然地覺得應該用const修飾數據成員來實現。const數據成員的確是存在的,但其含義卻不是我們所期望的。const數據成員只在某個對象生存期內是常量,而對于整個類而言卻是可變的,因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。
不能在類聲明中初始化const數據成員。以下用法是錯誤的,因為類的對象未被創建時,編譯器不知道SIZE的值是什么。
class A
{…
const int SIZE = 100; // 錯誤,企圖在類聲明中初始化const數據成員
int array[SIZE]; // 錯誤,未知的SIZE
};
const數據成員的初始化只能在類構造函數的初始化表中進行,例如
class A
{…
A(int size); // 構造函數
const int SIZE ;
};
A::A(int size) : SIZE(size) // 構造函數的初始化表
{
…
}
A a(100); // 對象 a 的SIZE值為100
A b(200); // 對象 b 的SIZE值為200
怎樣才能建立在整個類中都恒定的常量呢?別指望const數據成員了,應該用類中的枚舉常量來實現。例如
class A
{…
enum { SIZE1 = 100, SIZE2 = 200}; // 枚舉常量
int array1[SIZE1];
int array2[SIZE2];
};
枚舉常量不會占用對象的存儲空間,它們在編譯時被全部求值。枚舉常量的缺點是:它的隱含數據類型是整數,其最大值有限,且不能表示浮點數(如PI=3.14159)。
【規則5-3-1】需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部。為便于管理,可以把不同模塊的常量集中存放在一個公共的頭文件中。
【規則5-3-2】如果某一常量與其它常量密切相關,應在定義中包含這種關系,而不應給出一些孤立的值。
例如:
const float RADIUS = 100;
const float DIAMETER = RADIUS * 2;
類中的常量
有時我們希望某些常量只在類中有效。由于#define定義的宏常量是全局的,不能達到目的,于是想當然地覺得應該用const修飾數據成員來實現。const數據成員的確是存在的,但其含義卻不是我們所期望的。const數據成員只在某個對象生存期內是常量,而對于整個類而言卻是可變的,因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。
不能在類聲明中初始化const數據成員。以下用法是錯誤的,因為類的對象未被創建時,編譯器不知道SIZE的值是什么。
class A
{…
const int SIZE = 100; // 錯誤,企圖在類聲明中初始化const數據成員
int array[SIZE]; // 錯誤,未知的SIZE
};
const數據成員的初始化只能在類構造函數的初始化表中進行,例如
class A
{…
A(int size); // 構造函數
const int SIZE ;
};
A::A(int size) : SIZE(size) // 構造函數的初始化表
{
…
}
A a(100); // 對象 a 的SIZE值為100
A b(200); // 對象 b 的SIZE值為200
怎樣才能建立在整個類中都恒定的常量呢?別指望const數據成員了,應該用類中的枚舉常量來實現。例如
class A
{…
enum { SIZE1 = 100, SIZE2 = 200}; // 枚舉常量
int array1[SIZE1];
int array2[SIZE2];
};
枚舉常量不會占用對象的存儲空間,它們在編譯時被全部求值。枚舉常量的缺點是:它的隱含數據類型是整數,其最大值有限,且不能表示浮點數(如PI=3.14159)。
re: 我的java學習筆記(第一章 回顧C/C++ 基本概念) 噼里啪啦的世界 2005-04-01 06:50
常量
常量是一種標識符,它的值在運行期間恒定不變。C語言用 #define來定義常量(稱為宏常量)。C++ 語言除了 #define外還可以用const來定義常量(稱為const常量)。
為什么需要常量
如果不使用常量,直接在程序中填寫數字或字符串,將會有什么麻煩?
(1) 程序的可讀性(可理解性)變差。程序員自己會忘記那些數字或字符串是什么意思,用戶則更加不知它們從何處來、表示什么。
(2) 在程序的很多地方輸入同樣的數字或字符串,難保不發生書寫錯誤。
(3) 如果要修改數字或字符串,則會在很多地方改動,既麻煩又容易出錯。
【規則5-1-1】 盡量使用含義直觀的常量來表示那些將在程序中多次出現的數字或字符串。
例如:
#define MAX 100 /* C語言的宏常量 */
const int MAX = 100; // C++ 語言的const常量
const float PI = 3.14159; // C++ 語言的const常量
const 與 #define的比較
C++ 語言可以用const來定義常量,也可以用 #define來定義常量。但是前者比后者有更多的優點:
(1) const常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產生意料不到的錯誤(邊際效應)。
(2) 有些集成化的調試工具可以對const常量進行調試,但是不能對宏常量進行調試。
【規則5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。
re: 我的java學習筆記(第一章 回顧C/C++ 基本概念) 噼里啪啦的世界 2005-04-01 06:49
一、typedef的用法
____在C/C++語言中,typedef常用來定義一個標識符及關鍵字的別名,它是語言編譯過程的一部分,但它并不實際分配內存空間,實例像:
typedef int INT;
typedef int ARRAY[10];
typedef (int*) pINT;
____typedef可以增強程序的可讀性,以及標識符的靈活性,但它也有“非直觀性”等缺點。
二、#define的用法
____#define為一宏定義語句,通常用它來定義常量(包括無參量與帶參量),以及用來實現那些“表面似和善、背后一長串”的宏,它本身并不在編譯過程中進行,而是在這之前(預處理過程)就已經完成了,但也因此難以發現潛在的錯誤及其它代碼維護問題,它的實例像:
#define INT int
#define TRUE 1
#define Add(a,b) ((a)+(b));
#define Loop_10 for (int i=0; i<10; i++)
____在Scott Meyer的Effective C++一書的條款1中有關于#define語句弊端的分析,以及好的替代方法,大家可參看。
三、typedef與#define的區別
____從以上的概念便也能基本清楚,typedef只是為了增加可讀性而為標識符另起的新名稱(僅僅只是個別名),而#define原本在C中是為了定義常量,到了C++,const、enum、inline的出現使它也漸漸成為了起別名的工具。有時很容易搞不清楚與typedef兩者到底該用哪個好,如#define INT int這樣的語句,用typedef一樣可以完成,用哪個好呢?我主張用typedef,因為在早期的許多C編譯器中這條語句是非法的,只是現今的編譯器又做了擴充。為了盡可能地兼容,一般都遵循#define定義“可讀”的常量以及一些宏語句的任務,而typedef則常用來定義關鍵字、冗長的類型的別名。
____宏定義只是簡單的字符串代換(原地擴展),而typedef則不是原地擴展,它的新名字具有一定的封裝性,以致于新命名的標識符具有更易定義變量的功能。請看上面第一大點代碼的第三行:
typedef (int*) pINT;
以及下面這行:
#define pINT2 int*
____效果相同?實則不同!實踐中見差別:pINT a,b;的效果同int *a; int *b;表示定義了兩個整型指針變量。而pINT2 a,b;的效果同int *a, b;表示定義了一個整型指針變量a和整型變量b。
____注意:兩者還有一個行尾;號的區別哦!
____在C/C++語言中,typedef常用來定義一個標識符及關鍵字的別名,它是語言編譯過程的一部分,但它并不實際分配內存空間,實例像:
typedef int INT;
typedef int ARRAY[10];
typedef (int*) pINT;
____typedef可以增強程序的可讀性,以及標識符的靈活性,但它也有“非直觀性”等缺點。
二、#define的用法
____#define為一宏定義語句,通常用它來定義常量(包括無參量與帶參量),以及用來實現那些“表面似和善、背后一長串”的宏,它本身并不在編譯過程中進行,而是在這之前(預處理過程)就已經完成了,但也因此難以發現潛在的錯誤及其它代碼維護問題,它的實例像:
#define INT int
#define TRUE 1
#define Add(a,b) ((a)+(b));
#define Loop_10 for (int i=0; i<10; i++)
____在Scott Meyer的Effective C++一書的條款1中有關于#define語句弊端的分析,以及好的替代方法,大家可參看。
三、typedef與#define的區別
____從以上的概念便也能基本清楚,typedef只是為了增加可讀性而為標識符另起的新名稱(僅僅只是個別名),而#define原本在C中是為了定義常量,到了C++,const、enum、inline的出現使它也漸漸成為了起別名的工具。有時很容易搞不清楚與typedef兩者到底該用哪個好,如#define INT int這樣的語句,用typedef一樣可以完成,用哪個好呢?我主張用typedef,因為在早期的許多C編譯器中這條語句是非法的,只是現今的編譯器又做了擴充。為了盡可能地兼容,一般都遵循#define定義“可讀”的常量以及一些宏語句的任務,而typedef則常用來定義關鍵字、冗長的類型的別名。
____宏定義只是簡單的字符串代換(原地擴展),而typedef則不是原地擴展,它的新名字具有一定的封裝性,以致于新命名的標識符具有更易定義變量的功能。請看上面第一大點代碼的第三行:
typedef (int*) pINT;
以及下面這行:
#define pINT2 int*
____效果相同?實則不同!實踐中見差別:pINT a,b;的效果同int *a; int *b;表示定義了兩個整型指針變量。而pINT2 a,b;的效果同int *a, b;表示定義了一個整型指針變量a和整型變量b。
____注意:兩者還有一個行尾;號的區別哦!
re: 我的java學習筆記(第一章 回顧C/C++ 基本概念) 噼里啪啦的世界 2005-04-01 06:45
問題:const變量 & 常量
為什么我象下面的例子一樣用一個const變量來初始化數組,ANSI C的編譯器會報告一個錯誤呢?
const int n = 5;
int a[n];
答案與分析:
1)、這個問題討論的是“常量”與“只讀變量”的區別。常量肯定是只讀的,例如5, “abc”,等,肯定是只讀的,因為程序中根本沒有地方存放它的值,當然也就不能夠去修改它。而“只讀變量”則是在內存中開辟一個地方來存放它的值,只不過這個值由編譯器限定不允許被修改。C語言關鍵字const就是用來限定一個變量不允許被改變的修飾符(Qualifier)。上述代碼中變量n被修飾為只讀變量,可惜再怎么修飾也不是常量。而ANSI C規定數組定義時維度必須是“常量”,“只讀變量”也是不可以的。
2)、注意:在ANSI C中,這種寫法是錯誤的,因為數組的大小應該是個常量,而const int n,n只是一個變量(常量 != 不可變的變量,但在標準C++中,這樣定義的是一個常量,這種寫法是對的),實際上,根據編譯過程及內存分配來看,這種用法本來就應該是合理的,只是ANSI C對數組的規定限制了它。
3)、那么,在ANSI C 語言中用什么來定義常量呢?答案是enum類型和#define宏,這兩個都可以用來定義常量。
問題:const變量 & const 限定的內容
下面的代碼編譯器會報一個錯誤,請問,哪一個語句是錯誤的呢?
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
答案與分析:
問題出在p2++上。
1)、const使用的基本形式: const char m;
限定m不可變。
2)、替換1式中的m, const char *pm;
限定*pm不可變,當然pm是可變的,因此問題中p1++是對的。
3)、替換1式char, const newType m;
限定m不可變,問題中的charptr就是一種新類型,因此問題中p2不可變,p2++是錯誤的。
問題:const變量 & 字符串常量
請問下面的代碼有什么問題?
char *p = "i'm hungry!";
p[0]= 'I';
答案與分析:
上面的代碼可能會造成內存的非法寫操作。分析如下, “i'm hungry”實質上是字符串常量,而常量往往被編譯器放在只讀的內存區,不可寫。p初始指向這個只讀的內存區,而p[0] = 'I'則企圖去寫這個地方,編譯器當然不會答應。
問題:const變量 & 字符串常量2
請問char a[3] = "abc" 合法嗎?使用它有什么隱患?
答案與分析:
在標準C中這是合法的,但是它的生存環境非常狹??;它定義一個大小為3的數組,初始化為“abc”,,注意,它沒有通常的字符串終止符'\0',因此這個數組只是看起來像C語言中的字符串,實質上卻不是,因此所有對字符串進行處理的函數,比如strcpy、printf等,都不能夠被使用在這個假字符串上。
問題:const & 指針
類型聲明中const用來修飾一個常量,有如下兩種寫法,那么,請問,下面分別用const限定不可變的內容是什么?
1)、const在前面
const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可變
const (char *) pContent;//pContent是const,*pContent可變
char* const pContent; //pContent是const,*pContent可變
const char* const pContent; //pContent和*pContent都是const
2)、const在后面,與上面的聲明對等
int const nValue; // nValue是const
char const * pContent;// *pContent是const, pContent可變
(char *) const pContent;//pContent是const,*pContent可變
char* const pContent;// pContent是const,*pContent可變
char const* const pContent;// pContent和*pContent都是const
答案與分析:
const和指針一起使用是C語言中一個很常見的困惑之處,在實際開發中,特別是在看別人代碼的時候,常常會因為這樣而不好判斷作者的意圖,下面講一下我的判斷原則:
沿著*號劃一條線,const和誰在一邊,那么誰就是const,即const限定的元素就是它。你可以根據這個規則來看上面聲明的實際意義,相信定會一目了然。
另外,需要注意:對于const (char *) ; 因為char *是一個整體,相當于一個類型(如 char),因此,這是限定指針是const。
為什么我象下面的例子一樣用一個const變量來初始化數組,ANSI C的編譯器會報告一個錯誤呢?
const int n = 5;
int a[n];
答案與分析:
1)、這個問題討論的是“常量”與“只讀變量”的區別。常量肯定是只讀的,例如5, “abc”,等,肯定是只讀的,因為程序中根本沒有地方存放它的值,當然也就不能夠去修改它。而“只讀變量”則是在內存中開辟一個地方來存放它的值,只不過這個值由編譯器限定不允許被修改。C語言關鍵字const就是用來限定一個變量不允許被改變的修飾符(Qualifier)。上述代碼中變量n被修飾為只讀變量,可惜再怎么修飾也不是常量。而ANSI C規定數組定義時維度必須是“常量”,“只讀變量”也是不可以的。
2)、注意:在ANSI C中,這種寫法是錯誤的,因為數組的大小應該是個常量,而const int n,n只是一個變量(常量 != 不可變的變量,但在標準C++中,這樣定義的是一個常量,這種寫法是對的),實際上,根據編譯過程及內存分配來看,這種用法本來就應該是合理的,只是ANSI C對數組的規定限制了它。
3)、那么,在ANSI C 語言中用什么來定義常量呢?答案是enum類型和#define宏,這兩個都可以用來定義常量。
問題:const變量 & const 限定的內容
下面的代碼編譯器會報一個錯誤,請問,哪一個語句是錯誤的呢?
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
答案與分析:
問題出在p2++上。
1)、const使用的基本形式: const char m;
限定m不可變。
2)、替換1式中的m, const char *pm;
限定*pm不可變,當然pm是可變的,因此問題中p1++是對的。
3)、替換1式char, const newType m;
限定m不可變,問題中的charptr就是一種新類型,因此問題中p2不可變,p2++是錯誤的。
問題:const變量 & 字符串常量
請問下面的代碼有什么問題?
char *p = "i'm hungry!";
p[0]= 'I';
答案與分析:
上面的代碼可能會造成內存的非法寫操作。分析如下, “i'm hungry”實質上是字符串常量,而常量往往被編譯器放在只讀的內存區,不可寫。p初始指向這個只讀的內存區,而p[0] = 'I'則企圖去寫這個地方,編譯器當然不會答應。
問題:const變量 & 字符串常量2
請問char a[3] = "abc" 合法嗎?使用它有什么隱患?
答案與分析:
在標準C中這是合法的,但是它的生存環境非常狹??;它定義一個大小為3的數組,初始化為“abc”,,注意,它沒有通常的字符串終止符'\0',因此這個數組只是看起來像C語言中的字符串,實質上卻不是,因此所有對字符串進行處理的函數,比如strcpy、printf等,都不能夠被使用在這個假字符串上。
問題:const & 指針
類型聲明中const用來修飾一個常量,有如下兩種寫法,那么,請問,下面分別用const限定不可變的內容是什么?
1)、const在前面
const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可變
const (char *) pContent;//pContent是const,*pContent可變
char* const pContent; //pContent是const,*pContent可變
const char* const pContent; //pContent和*pContent都是const
2)、const在后面,與上面的聲明對等
int const nValue; // nValue是const
char const * pContent;// *pContent是const, pContent可變
(char *) const pContent;//pContent是const,*pContent可變
char* const pContent;// pContent是const,*pContent可變
char const* const pContent;// pContent和*pContent都是const
答案與分析:
const和指針一起使用是C語言中一個很常見的困惑之處,在實際開發中,特別是在看別人代碼的時候,常常會因為這樣而不好判斷作者的意圖,下面講一下我的判斷原則:
沿著*號劃一條線,const和誰在一邊,那么誰就是const,即const限定的元素就是它。你可以根據這個規則來看上面聲明的實際意義,相信定會一目了然。
另外,需要注意:對于const (char *) ; 因為char *是一個整體,相當于一個類型(如 char),因此,這是限定指針是const。