1、判斷
void main(){
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
std::cout << std::boolalpha << ( str1==str2 ) << std::endl; //false
std::cout << std::boolalpha << ( str3==str4 ) << std::endl; // false
std::cout << std::boolalpha << ( str5==str6 ) << std::endl; // true
/*分別輸出字符串的地址
str1,str2,str3,str4位於棧區,向低地址增長
str5,str6位於只讀數據區,所以地址相同
*/
printf("%p\t%p\n",str1,str2);
printf("%p\t%p\n",str3,str4);
printf("%p\t%p\n",str5,str6);
system("pause");
}
解答:分別輸出false,false,true
str1和str2都是字符數組,每個都有自己的存儲器,數組名的值則是各存儲器的首地址,所以不等。
str3和str4同上,只是按const語義,他們所指向的數據區不能修改。
str5和str6不是數組而是字符指針,並沒有分別存儲器,"abc"以常量形式存於靜態數據區,指針則指向該區的首地址,所以相等。
2、 將 str 中的小寫字母轉換成大寫字母
void UpperCase( char str[] )
{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
UpperCase函數傳遞指針,sizeof(str)==4,字符串長度超過4,就不能夠轉換3、非C++內建型別A和B, 在哪幾種情況下B能隱式轉化爲A?
- // Case 1 : B公有繼承自A
- class B : public A
- {
- ...
- }
- // Case 2 : B實現了隱式轉化爲A的轉化
- class B
- {
- operator A();
- }
- // Case 3 : A實現了non-explicit的參數爲B的構造函數
- class A
- {
- A(const B&);
- }
- // Case 4 : 賦值操作
- A & operator=(const A&);
5、c++空類默認產生的類成員函數
//c++空類默認產生的類成員函數
class Empty
{
public:
Empty();//缺省構造函數
Empty(const Empty&);//拷貝構造函數
~Empty();//析構函數
Empty& operator=(const Empty&);//賦值運算符
Empty* operator&();//取址運算符
const Empty* operator&() const;//取址運算符const
6判斷
//1以整數形式存放和以浮點形式存放其內存數據是不一樣的,因此兩者不等
float a = 1.0f;
cout<<(int)a<<endl;//實際上是以浮點數 a爲參數構造了一個整型數1,
cout<<(int&)a<<endl;//告訴編譯器將a當作整數看(並沒有做任何實質上的轉換)
//0以整數形式存放和以浮點形式存放其內存數據是一樣的,因此兩者相等
float b = 0.0f;
cout<<(int)b<<endl;
cout<<(int&)b<<endl;
7、定義 int **a[3][4], 則變量佔有的內存空間爲:_____ ?
分析:由於優先級[]>*,所以a是存放二級指針的二維數組;
若(**a)[3][4],則a爲指向二維數組的指針;
4、判斷
struct Test
{
Test(int){}
Test(){}
void fun(){}
};
Test a(1);
a.fun();
Test b();//Error,默認構造函數初始化不加括號
b.fun();
8、數組和指針的區別
數組可以再靜態存儲區和棧上建立,指針可以指向任意類型的存儲塊
9、判斷輸出
main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%s\n”,p2);//p2指向字符串末端,爲空
}
10使用strcat()
main()
{
char *p1;
char *p2;
p1=(char *)malloc(25);
p2=(char *)malloc(25);
strcpy(p1,”Cisco”);
strcpy(p2,“systems”);
strcat(p1,p2);//注意空間的處理
printf(“%s”,p1);
}
儘管給p1,p2都分配了25字節的內存,但是使用strcat可以將函數連接在一起
11有哪幾種情況只能用intialization list而不能用assignment?
當類中含有 const、reference 成員變量;基類的構造函數都需要初始化表。
12、初始化vector
vector< vector<int>> ivv;
ivv[0].push_back(1);
cout<<ivv[0][0]<<endl;
-----------------------------代碼錯誤,沒有初始化vector<int>就使用
vector<vector<int>> ivv;
ivv.push_back(vector<int>());
ivv[0].push_back(1);
cout<<ivv[0][0]<<endl;
------------------------------可以使用vector<vector<int>> ivv(10);進行多數的初始化13.繼承的優缺點
1、類繼承是在編譯時刻靜態定義的,且可直接使用,
2、類繼承可以較方便地改變父類的實現。(對於子類改變父類的實現)
缺點:
1、因爲繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現
2、父類通常至少定義了子類的部分行爲,父類的任何改變都可能影響子類的行爲
3、如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。
這種依賴關係限制了靈活性並最終限制了複用性。
14、c++在頭文件中進行類的聲明,在對應的實現文件中進行類的定義有什麼意義?
h爲編譯器提供一個索引,連接obj對象和主程序
編譯器在編譯的時候,如果需要,則去查找h,找到了h,再找對應的obj,就可以找到類的方法了
但是如果直接寫入到同一個文件(例如hpp),主程序沒有索引,也不清楚具體的類實現了沒有,只能一次次重複的編譯相同的代碼,這樣實際上沒有把這個類該有的東西抽象出來