C++Day5
一、選擇題
1、關於對象概念的描述中,(A )是錯誤的。
A.對象就是C語言中的結構體 B.對象是狀態和操作的封裝體
C.對象之間的信息傳遞是通過消息進行的 D.對象是某個類的一個實例
2、下列說法中正確的是( B )
A.類定義中只能說明函數成員的函數頭,不能定義函數體
B.類中的成員函數可以在類體中定義,也可以在類體外定義
C.類中的函數成員在類體外定義時必須要與類聲明在同一文件中
D.在類體之外定義的函數成員不能操作該類的私有數據成員
3、有關析構函數的說法不正確的是__________。( C)
A.析構函數有且只有一個
B.析構函數無任何函數類型
C.析構函數和構造函數一樣可以有形參
D.析構函數的作用是在對象被撤銷時收回先前分配的內存空間
4、定義析構函數時,應該注意(C )
A.其名與類名完全相同 B.返回類型是void類型
C.無形參,也不可重載 D.函數體中必須有delete語句
5、每個類( C )構造函數。
A.只能有一個 B.只可有公有的
C.可以有多個 D.只可有缺省的
6、在類中說明的成員可以使用關鍵字( AD )進行修飾。(多選題)
A.private B.extern C.auto D.public E.register
7、下列關於對象數組的描述中,那個是錯的。( D )
A.對象數組的下標是從0開始的
B.對象數組的數組名是一個常量指針//按照這個理解,應該是指針常量,所以這里也有問題
C.對象數組的每個元素是同一個類的對象
D.對象數組的只能賦初值,而不能被賦值
8、對類的構造函數和析構函數描述正確的是( A)。
A. 構造函數可以重載,析構函數不能重載
B. 構造函數不能重載,析構函數可以重載
C. 構造函數可以重載,析構函數也可以重載
D. 構造函數不能重載,析構函數也不能重載
9、假設Base為一個類,則該類的拷貝初始化構造函數的聲明語句為(C )。
A.Base(const Base rhs); B.Base &(const Base rhs);
C.Base(const Base &rhs);D.Base (const Base *rhs);
10、有關類的說法不正確的是_________。( D)
A.類是一種用戶自定義的數據類型
B.只有類中的成員函數才能存取類中的私有數據
C.在類中,如果不作特別說明,所有的數據均為私有類型
D.在類中,如果不作特別說明,所有的成員函數均為公有類型
11、以下關於this指針的敘述中正確的是:( D )
A.任何與類相關的函數都有this指針 B.類的成員函數都有this指針
C.類的友員函數都有this指針 D.類的非靜態成員函數才有this指針
12、this指針存在的目的是:( B)
A.保證基類公有成員在子類中可以被訪問
B.保證每個對象擁有自己的數據成員,但共享處理這些數據成員的代碼
C.保證基類保護成員在子類中可以被訪問
D.保證基類私有成員在子類中可以被訪問
13、下面對靜態數據成員的描述中,正確的是( B )。
A.靜態數據成員可以在類體內進行初始化
B.靜態數據成員不可以在類體內進行初始化
C.靜態數據成員不能受private控制符的作用
D.靜態數據成員可以直接用類名調用
14、下面對靜態數據成員的描述中,正確的是( A )。
A.靜態數據成員是類的所有對象共享的數據
B.類的每一個對象都有自己的靜態數據成員
C.類的不同對象有不同的靜態數據成員值
D.靜態數據成員不能通過類的對象調用
15、關於靜態成員的描述中,( B )是錯誤的。
A.靜態成員可分為靜態數據成員和靜態成員函數
B.靜態數據成員定義后必須在類體內進行初始化
C.靜態數據成員初始化不使用其構造函數
D.靜態數據成員函數中不能直接引用非靜態成員
16、已知:print()函數是一個類的常成員函數,它無返回值,下列表示中,是正確的。( A )
A.void print() const; B.const void print();
C.void const print(); D.void print(const);
17、下面有關類的靜態成員和非靜態成員,說法錯誤的是?(C )
A.靜態成員存在於內存,非靜態成員需要實例化才會分配內存
B.非靜態成員可以直接訪問類中靜態的成員
C.靜態成員能訪問非靜態的成員
D.非靜態成員的生存期決定於該類的生存期,而靜態成員生存期則與程序生命期相同
二、編程題P
1、實現上課時候的單例模式的代碼
#include<bits/stdc++.h>
using namespace std;
class Singleton{
private:
static Singleton *instance;//類的私有靜態指針變量
int _data;
private:
Singleton()
:_data(100)
{}
~Singleton(){
cout<<"~Singleton()"<<endl;
}
public:
static Singleton* getInstance(){
if(instance==nullptr){
instance=new Singleton();
}
return instance;
}
static void destroy(){
if(instance){
delete instance;
instance=nullptr;
}
}
void print()const{
cout<<"i come:"<<_data<<endl;
}
};
Singleton* Singleton::instance=nullptr;
void test0(){
Singleton::getInstance()->print();
Singleton::destroy();
}
int main(){
test0();
return 0;
}
jing@jing:~/code/2022-3-31$ ./Singleton
i come:100
~Singleton()
2、上課的時候,單例模式的代碼中,對象是放在堆上的,大家可以看看除了堆還有什么地方可以存放這個唯一的對象,並實現相應的代碼。
#include<bits/stdc++.h>
using namespace std;
class Singleton{
private:
static Singleton *instance;//類的私有靜態指針變量
int _data;
private:
Singleton()
:_data(100)
{}
~Singleton(){
cout<<"~Singleton()"<<endl;
}
public:
static Singleton* getInstance(){
static Singleton instance;
return &instance;
}
static void destroy(){
if(instance){
delete instance;
instance=nullptr;
}
}
void print()const{
cout<<"i come:"<<_data<<endl;
}
};
Singleton* Singleton::instance=nullptr;
void test0(){
Singleton *s1=Singleton::getInstance();
Singleton *s2=s1;
Singleton *s3=Singleton::getInstance();
cout<<s1<<endl<<s2<<endl<<s3<<endl;
s1->print();
}
int main(){
test0();
return 0;
}
jing@jing:~/code/2022-3-31$ ./Singleton_stack_1
0x56334dec2144
0x56334dec2144
0x56334dec2144
i come:100
~Singleton()
3、分別實現new/delete表達式中只能生成棧對象的代碼和只能生成堆對象的代碼。
//heap.cc
#include<bits/stdc++.h>
using namespace std;
class Student{
private:
int _id;
char *_name;
public:
Student(int id,const char* name)
:_id(id)
,_name(new char[strlen(name)+1]())
{
cout<<"Student()"<<endl;
strcpy(_name,name);
}
void print() const{
cout<<"id:"<<_id<<endl
<<"name:"<<_name<<endl;
}
void destroy(){
delete this;
}
private:
~Student(){
if(_name){
delete[] _name;
_name=nullptr;
}
cout<<"~Student"<<endl;
}
public:
//空間申請
void * operator new(size_t sz){
cout<<"void* operator new (size_t)"<<endl;
void * pret=malloc(sz);
return pret;
}
//回收
void operator delete(void *pret){
cout<<"void operator delete(void*)"<<endl;
free(pret);
}
};
void test0(){
//堆
Student *ps1=new Student(1001,"czj");
ps1->print();
ps1->destroy();
}
int main(){
cout<<sizeof(Student)<<endl;
test0();
return 0;
}
jing@jing:~/code/2022-3-31$ ./Singleton_heap
16
void* operator new (size_t)
Student()
id:1001
name:czj
~Student
void operator delete(void*)
stack.cc
#include<bits/stdc++.h>
using namespace std;
class Student{
private:
int _id;
char *_name;
public:
Student(int id,const char* name)
:_id(id)
,_name(new char[strlen(name)+1]())
{
cout<<"Student()"<<endl;
strcpy(_name,name);
}
void print() const{
cout<<"id:"<<_id<<endl
<<"name:"<<_name<<endl;
}
~Student(){
if(_name){
delete[] _name;
_name=nullptr;
}
cout<<"~Student"<<endl;
}
public:
//空間申請
void * operator new(size_t sz){
cout<<"void* operator new (size_t)"<<endl;
void * pret=malloc(sz);
return pret;
}
//回收
void operator delete(void *pret){
cout<<"void operator delete(void*)"<<endl;
free(pret);
}
};
void test0(){
Student s2(1001,"czj");
s2.print();
}
int main(){
cout<<sizeof(Student)<<endl;
test0();
return 0;
}
jing@jing:~/code/2022-3-31$ ./Singleton_stack
16
Student()
id:1001
name:czj
~Student
三、算法題(選做)
1、題目:輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有奇數位於數組的前半部分,所有偶數位於數組的后半部分。
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
int len=s.size();
string s1;
int x;
for(int i=0;i<s.size();i++){
x=s[i]-'0';
if(x%2==1){
s1+=s[i];
s[i]='\0';
}
}
for(int i=0;i<s.size();i++){
if(s[i]!='\0'){
s1+=s[i];
}
}
cout<<s1;
return 0;
}
jing@jing:~/code/2022-3-31$ ./1
12345
13524
2、題目:請實現一個函數用來判斷字符串是否表示數值(包括整數和小數)。例如,字符串“+100”、“5e2”、“-123”、“3.1416”及“-1E-16”都表示數值,但“12e”、“1a3.14”、“1.2.3”、“+-5”及“12e+5.4”都不是。
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
int flag1,flag2;
flag1=flag2=1;
while(cin>>s){
for(int i=0;i<s.size();i++){
if((s[0]=='-'||s[0]=='+')&&flag1==1){//處理一開始的符號,如果是+或-,則跳到下一個
flag1=0;
continue;
}
else if((s[i]=='-'||s[i]=='+')&& flag1==0){
cout<<"no"<<endl;
break;
}
else{
if(s[i]!='.'&&s[i]!='e'&&s[i]!='E'){
if(i==s.size()-1){
cout<<"yes"<<endl;
}
}else if((s[i]=='.')&&flag2==1){
flag2=0;
continue;
}else if((s[i]=='.')&&flag2==0){
cout<<"no"<<endl;
break;
}else if((s[i]=='e')&&(i==s.size()-1)){
cout<<"no"<<endl;
break;
}
}
}
}
return 0;
}