We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近一段时间笔者整理了2022春OOP六次作业中的选择题,从中选出了一部分题目的选项进行解析,希望能够帮助同学们提高期末复习的效率(然而事实是在整理完这篇笔记后发现自己已经彻底复习不完了/(ㄒoㄒ)/~~)
A. 对于下列代码中的两个运算符重载实现:即便它们的参数均为 int 与 Test 的组合,这段代码仍可以通过编译。这是因为在两个重载实现中, int 与 Test 在参数中的顺序不同,编译器能够唯一地确定调用哪个运算符实现代码。
int
Test
#include <iostream> using namespace std; class Test{ public: int data; Test(int d):data(d){} }; Test operator +(const Test& a, const int& b){ return Test(a.data + b); } Test operator +(const int& b, const Test& a){ return Test(- a.data - b); } int main(){ Test obj(1); int data = 2; cout << (obj + data).data << endl; cout << (data + obj).data << endl; return 0; }
运算符重载时,不必考虑可交换性和多参数类型
#include <iostream> class Test{ public: int data = -1; Test() = default; // (A) Test(int dat){ // (B) this->data = dat; // (C) } ~Test(){ // (D) std::cout<<data; } }; int main(){ Test* t = new Test(); delete t; return 0; }
D. (不考虑 A、B、C 选项的改动,)如果将注释 (D) 所在的行改为 ~Test(int data = 0){ // (D),该代码可以通过编译,运行输出结果为 0。析构函数不能带有参数
(D)
~Test(int data = 0){ // (D)
0
关于构造函数和析构函数,阅读以下可以通过编译的代码,并选出其运行输出结果:
#include <iostream> class Member{ public: Member(){std::cout<<"Constructing member.";} ~Member(){std::cout<<"Destructing member.";} }; class Group{ public: Member member; Group(){std::cout<<"Constructing group.";} ~Group(){std::cout<<"Destructing group.";} }; int main(){ Group group; return 0; }
A. Constructing member.Constructing group.Destructing member.Destructing group.
Constructing member.Constructing group.Destructing member.Destructing group.
B. Constructing member.Constructing group.Destructing group.Destructing member.
Constructing member.Constructing group.Destructing group.Destructing member.
C. Constructing group.Constructing member.Destructing member.Destructing group.
Constructing group.Constructing member.Destructing member.Destructing group.
D. Constructing group.Constructing member.Destructing group.Destructing member.
Constructing group.Constructing member.Destructing group.Destructing member.
创建和销毁的原则:创建时先成员后整体,销毁时先整体后成员,早创建的晚销毁
#include <iostream> class Student{ friend class School; private: // (B) ~Student(){std::cout<<"Student fired.";} public: class School* school; void interfereSchool(); }; class School{ private: void access(){std::cout<<"School accessed.";} public: Student* student; void fireStudent(); }; void Student::interfereSchool(){ school -> access(); // (A) } void School::fireStudent(){ delete student; } int main(){ School* school = new School(); Student* student = new Student(); school -> student = student; student -> school = school; student -> interfereSchool(); school -> fireStudent(); }
B. 该代码不能通过编译,原因:Student 类的析构函数被定义为私有成员。解决方案:将其更改为公有成员(即:将代码中注释 (B) 所在的行改为 public:),方可通过编译。应该更改的是School类中的access函数权限
Student
(B)
public:
class Student{ private: const int id; double gpa; public: Student(int _id): id(_id), gpa(0.0) {} // (A) int getId() const { return id; } void updateGpa(double _gpa) { gpa = _gpa; } double getGpa() { return gpa; } }; int main(){ Student alice(1); alice.getId(); alice.updateGpa(4.0); alice.getGpa(); const Student bob(2); bob.getId(); return 0; }
A. 使用 Student(int _id) {id = _id; gpa = 0.0;} 替换原代码中的 Student 类构造函数(即注释 (A) 所在的行)不会影响编译,因为它们的效果是完全一致的。常量只能用初始化列表定义,不能在函数体中定义
Student(int _id) {id = _id; gpa = 0.0;}
(A)
B. 在 main 函数中 bob 对象定义后,可以调用 bob.getGpa(),因为没有对 bob 的任何成员变量作修改。常量只能调用常量函数,即使非常量函数没有更改常量数据成员,这依然是很危险的不被允许的行为
main
bob
bob.getGpa()
D. Student 类的 getGpa 成员函数不能改为常量成员函数,因为该函数的实现中访问了非常量成员 gpa。常量成员函数可以访问变量,但不能改变变量
getGpa
gpa
课件中对常量、静态成员的总结表格:
A. 使用 new[] 构造的对象应当使用 delete 释放内存,如下面代码所示。new[]要配合delete[]用
new[]
delete
class Test{}; int main() { Test* a = new Test[10]; delete a; return 0; }
2.【单选】以下代码的输出是:
01 #include<iostream> 02 using namespace std; 03 04 class T{ 05 public: 06 T(){} 07 T(T& t){cout<<"A";} 08 T(T&& t){cout<<"B";} 09 T& operator =(T&& t){cout<<"C"; return *this;} 10 }; 11 12 void swap(T& a, T& b) { 13 T tmp(std::move(a));//调用移动构造函数 14 a = std::move(b);//调用移动赋值函数 15 b = std::move(tmp);//调用移动赋值函数 16 } 17 18 int main(){ 19 T a; 20 T b; 21 swap(a,b); 22 return 0; 23 }
B) BCC 先移动构造再两次移动赋值
3.【多选】关于以下代码说法正确的有:
01 #include <iostream> 02 using namespace std; 03 04 class Complex 05 { 06 public: 07 int real; 08 int imag; 09 Complex():real(0),imag(0){} 10 Complex(int r, int i):real(r),imag(i){cout<<"B";} 11 Complex(int r): real(r),imag(0){cout<<"A";} 12 operator int(){ 13 return real; 14 } 15 Complex operator+(const Complex& c){ 16 return Complex(this->real+c.real,this->imag+c.imag); 17 } 18 }; 19 20 int main() 21 { 22 Complex c(3,4); 23 c=c+3.4; 24 cout<<c.real+c.imag; 25 return 0; 26 }
B) 如果注释15-17行,并且在12行前加explicit关键字,则第23行不可以通过编译。 explicit 关键词加入后类型转换需显式定义(L6p56)
C) 如果注释12-14行,输出结果是BA10。BAB10,还有一个浅拷贝的构造
D) 如果注释15-17行,输出结果是BA10。BA6,c=c+3.4c转化成int型后再调用构造函数
c=c+3.4
【单选】下面说法错误的有:
C) int a=5; int &&x=a;是合法的语句。无法将右值引用绑定到左值
6.【单选】关于下面这段代码运行结果说法正确的有 (编译选项含有-std=c++11):
01 #include <iostream> 02 using namespace std; 03 class A { 04 int data; 05 public: 06 static int count; 07 A():data(2019){count += 1; cout << count << endl;} 08 A& operator = (const A & a){ 09 if (this != &a) data = a.data; 10 return *this; 11 } 12 A(int i):data(i){count += 2; cout << count << endl;} 13 ~A(){cout << "destructor "<< data << endl;} 14 }; 15 16 class B { 17 int data{2020}; 18 A a1,a2; 19 public: 20 B(){} 21 B(int i):a2(i){a1 = a2;} 22 ~B(){cout<<"destructor "<< data <<endl;} 23 }; 24 25 int A::count = 0; 26 27 int main() { 28 B obj1; 29 B obj2(2021); 30 return 0; 31 }
B) 输出的前4行是1\n2\n4\n5\n。 1235,按照声明的顺序而非初始化列表的顺序构造A
D) 输出中前缀是destructor的行,后面的数字按顺序是2020,2021,2021,2020,2019,2019。析构先整体后成员
7.【单选】关于下面代码说法正确的有:
01 #include <iostream> 02 using namespace std; 03 04 class Animal{ 05 public: 06 Animal(){}; 07 Animal(int d){}; 08 void move(double d) { cout << "Animal move" << d << "km\n"; } 09 void eat(double d) { cout << "Animal eat " << d << "g food\n"; } 10 }; 11 12 class Bird: public Animal{ 13 public: 14 using Animal::move; 15 void move() { cout << "Bird move"; } 16 void move(int i) { cout << "Bird move" << i << "m\n"; } 17 }; 18 19 class Crow : public Bird{ 20 public: 21 using Bird::move; 22 void move(int i) { cout << "Crow move" << i << "m\n"; } 23 }; 24 25 int main() { 26 Crow crow; 27 crow.move(10); 28 crow.move(4.9); 29 crow.eat(4.8); 30 crow.move(); 31 return 0; 32 }
D) 如果将第12行改为class Bird: protected Animal{, 只需要去掉第29行就可以成功编译运行。protected成员无法通过对象访问
8.【多选】以下说法正确的有: A) 派生类的成员函数可以访问通过私有继承的基类的保护成员。只要是protected就可以被派生类函数访问
D) 派生类的构造函数的成员初始化列表中,可以包含基类数据成员的初始化。派生类不能直接初始化基类成员变量
2.【单选】下列说法正确的是
B. 在基类中所有的纯虚函数都不必定义函数体(虚析构函数一定要定义函数体实现)
3.【多选】对下面代码,无法编译通过的有
#include <iostream> using namespace std; class Base{ public: void func1() {cout << "Base::func1()" << endl;} virtual void func2() {cout << "Base::func2()" << endl;} virtual void func2(int) {cout << "Base::func2(int)" << endl;} void func2(float) {cout << "Base::func2(float)" << endl;} // (1) }; class Derived1: public Base{ public: void func1() final {cout << "Derived1::func1()" << endl;} // (2)不能使用 "final" 修饰符声明非虚函数 void func2(float) {cout << "Derived1::func2(float)" << endl;} }; class Derived2: public Base{ public: void func2(int) final override {cout << "Derived2::func2(int)" << endl;} // (3) }; int main(){ Derived1 obj; obj.func2(); // (4) 函数调用中的参数太少 return 0; }
4.【单选】下列说法正确的有 A. 抽象类中一定有某个成员函数没有函数体(虚析构函数一定要有函数体)
B. 抽象类的派生类就不是抽象类了(要看有没有重写覆盖)
C. 只有当一个抽象类的派生类中将该抽象基类的所有纯虚函数都重写覆盖,该派生类才不再是抽象类(析构函数会自动生成,不需要手动重写覆盖)
5.【单选】关于类型转换,说法正确的有 A. 若Derived是Base的派生类,p为Base类的指针,指向了Derived的对象,则dynamic_cast<Derived*>(p)就可以正确返回Derived的指针(前提是Base和Derived有虚函数关系)
D. dynamic_cast只能用于向下类型转换(dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting),只是向上类型转换十分安全一般不用调用这个函数)
6.【多选】关于多态,下面说法正确的是
C. 指针、引用对虚函数的调用总是晚绑定,即运行时绑定(p->Base::func()通过类名可以强制早绑定)
7.【单选】关于下面代码,说法正确的是
#include <iostream> using namespace std; template<typename T0> T0 func(T0 a, T0 b){ T0 c = a + b; return c; } template<typename T1> T1 func2(T1 a, T1 b){ T1 c = a - b; return c; } int main(){ int a = func(1.2, 1.3); // (1) int b = func2(func(1, 2), func(2, 3)); //(2) int c = func(1, 1.2); // (3) int d = func<int>(1, 1.2); // (4) return 0; }
C. (3) 处的返回值为2,第二个参数1.2被强制类型转换成了 int 类型(需要强制类型转换,否则编译器会认为找不到符合(int,float)参数类型的函数)
1.【单选】请阅读或执行以下代码,下列说法正确的是
#include <iostream> #include <string> namespace Campus { int building_number; }; namespace ComputerScience { using Campus::building_number; std::string dean; struct Student { std::string id; int age; }; int student_number; void setDean(std::string name) { dean = name; } void setStudentNumber(int number) { student_number = number; } void setStudent(Student &s, std::string id, int age) { s.id = id; s.age = age; } }; namespace THU { using namespace ComputerScience; std::string principle; int student_number; void setStudentNumber(int number) { student_number = number; } void setPrinciple(std::string name) { principle = name; } }; void choiceA() { using namespace THU; setStudentNumber(10000); // (1) } void choiceB() { using namespace THU; ComputerScience::setStudentNumber(1000); // (2) } void choiceC() { using namespace THU; ComputerScience::setStudentNumber(1000); THU::setStudentNumber(10000); std::cout << student_number; // (3) } void choiceD() { using THU::setDean; setDean("Xia Yin"); // (4) } void choiceE() { using Campus::building_number; using ComputerScience::building_number; using THU::building_number; } int main() { choiceA(); choiceB(); choiceC(); choiceD(); choiceE(); }
B. choiceB()中(2)处不能调用ComputerScience::setStudentNumber,因为命名空间THU将命名空间ComputerScience隐藏了,只声明命名空间THU无法使用命名空间ComputerScience中的函数(namespace无重写隐藏功能)
choiceB()
ComputerScience::setStudentNumber
THU
ComputerScience
E. choiceE()可正常编译运行,其中的三个using声明是合法的(只要最后using的是同一个东西就不会报错)
choiceE()
using
2.【多选】请阅读或执行以下代码,下列说法正确的是
#include <iostream> #include <tuple> void choiceA() { std::tuple<int, std::string> a; } void choiceB() { std::tuple<int, int> a; auto b = std::make_tuple(2022, 2023); a = b; } void choiceC() { std::tuple<int, int> a; auto b = std::make_tuple(2022, 2023); a = b; std::cout << std::get<0>(a) << " " << std::get<1>(a) << std::get<2>(a) << std::endl; } void choiceD() { std::tuple<int, int> a = std::make_tuple(1299, 1923); int number1; int number2; a = std::tie(number1, number2) = std::make_tuple(395, 1453); } void choiceE() { std::tuple<int, int, int> long_tuple = std::make_tuple(0, 0, 0); std::tuple<int, int> short_tuple = long_tuple; } int main() { choiceA(); choiceB(); choiceC(); choiceD(); choiceE(); return 0; }
E. choiceE()会出现编译错误或运行异常(不同维数的tuple不能相互转换)
3.【单选】请阅读或执行以下代码,下列说法正确的是
#include <iostream> #include <vector> class Data { private: int _num; public: Data(int num) : _num(num) { std::cout << "构造函数" << std::endl; } Data(const Data& d) : _num(d._num) { std::cout << "拷贝构造函数" << std::endl; } Data(Data&& d) : _num(d._num) { std::cout << "移动构造函数" << std::endl; } Data& operator=(const Data& d) { this->_num = d._num; std::cout << "拷贝赋值" << std::endl; return *this; } ~Data() { std::cout << "析构函数" << std::endl; } }; void choiceA() { std::vector<int> vec = {1, 2, 3, 4, 5}; auto end = vec.end(); auto begin = vec.begin(); std::cout << *begin << " " << *end << std::endl; // (1) } void choiceB() { std::vector<int> vec = {1, 2, 3, 4, 5}; auto begin_add_2 = vec.begin() + 2; auto result = vec.erase(begin_add_2); std::cout << *result << std::endl; // (2) } void choiceC() { std::vector<int> vec = {1, 2, 3, 4, 5}; auto end = vec.end(); auto begin_add_2 = vec.begin() + 2; auto result = vec.erase(begin_add_2); // (3) std::cout << *end << std::endl; } std::ostream& operator << (std::ostream& output, std::vector<int>& v) { for (int i = 0; i < v.size(); ++i) { output << v[i] << " "; } output << std::endl; return output; } void choiceD() { std::vector<int> vec = {1, 2, 3, 4, 5}; std::cout << vec; // (4) } void choiceE() { std::vector<Data> vec; for (int i = 0; i < 4; ++i) { vec.push_back(Data(i)); } auto begin = vec.begin(); std::cout << "==分割线==" << std::endl; vec.insert(begin, Data(100)); // (5) std::cout << "==分割线==" << std::endl; } int main() { choiceA(); choiceB(); choiceC(); choiceD(); choiceE(); return 0; }
A. choiceA()可正常编译运行,(1)处输出1 5(end指向最后一个元素的下一个位置)
choiceA()
1 5
B. choiceB()可正常编译运行,(2)处输出3(erase函数返回的是删除元素的下一个元素的迭代器)
3
D. 对于choiceD(),如果删去函数operator <<,(4)处的<<将调用vector的默认重载流运算符方法(vector未默认重载流运算符)
choiceD()
operator <<
<<
vector
4.【多选】请阅读或执行以下代码,下列说法正确的是
#include <iostream> #include <list> void choiceA(std::list<int> lst) { auto begin = lst.begin(); for (int i = 0; i < 2; ++i) { begin ++; } *begin = 100; } void choiceB(std::list<int> lst) { lst[2] = 100; } void choiceC(std::list<int> lst) { auto result = std::find(lst.begin(), --lst.end(), 100); std::cout << *result << std::endl; // (1) } void choiceD(std::list<int> lst) { auto begin = lst.begin(); auto end = --lst.end(); lst.insert(begin, 101); std::cout << *end << std::endl; // (2) } void choiceE(std::list<int> lst) { auto result = std::find(lst.begin(), lst.end(), 4); lst.erase(result); --result; std::cout << *result << std::endl; // (3) } int main() { std::list<int> lst; for (int i = 0; i < 5; ++i) { lst.push_back(i * 2); } choiceA(lst); choiceB(lst); choiceC(lst); choiceD(lst); choiceE(lst); return 0; }
B. choiceB()中可以修改传入lst中的第2个位置上的元素(约定lst.begin()是指向第0个位置的迭代器)(list无法通过下标方式访问)
lst
lst.begin()
E. choiceE()中(3)处会出现运行错误,因为erase操作使得迭代器result失效(listl类型插入和删除操作不会导致迭代器失效(除指向被删除的元素的迭代器外))
erase
result
5.【多选】请阅读或执行以下代码,下列说法正确的是
#include <iostream> #include <map> void choiceA(std::map<std::string, int> m) { m["Monday"] = 100; // (1) std::cout << m.count("Monday") << std::endl; // (2) } void choiceB(std::map<std::string, int> m) { m.insert(std::pair<int, std::string>(200, "Tuesday")); // (3) std::cout << m.count("Tuesday") << std::endl; // (4) } void choiceC(std::map<std::string, int> m) { auto result = m.find("May"); auto tmp = result == m.end(); std::cout << tmp << std::endl; // (5) } void choiceD(std::map<std::string, int> m) { m.erase(++m.begin(), --m.end()); std::cout << m.size() << std::endl; // (6) } void choiceE(std::map<std::string, int> m) { for (auto element: m) { std::cout << element.first << " "; } std::cout << std::endl; } int main() { std::map<std::string, int> m; m["Sunday"] = 0; m["Monday"] = 1; m["Tuesday"] = 2; m["Wednesday"] = 3; m["Thursday"] = 4; m["Friday"] = 5; m["Saturday"] = 6; choiceA(m); choiceB(m); choiceC(m); choiceD(m); choiceE(m); return 0; }
D. choiceD()中(6)处的输出是1(2,保留了首尾,erase函数遵循左闭右开原则)
1
E. choiceE()的输出是Sunday Monday Tuesday Wednesday Thursday Friday Saturday,以换行符结尾。(每添加一个元素会根据首元素的字符串的字典序顺序重新排序)
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
7.【多选】阅读以下代码(linux环境下保存为main.sh)
main.sh
#!/bin/bash filename=test for par in $@; do mkdir output-$par && python ${filename}.py $par done
同目录下的test.py为
test.py
import sys print(sys.argv[1])
这个python脚本的意义为打印传递给脚本的一个参数,例如python test.py 2022oop,其执行结果为输出2022oop。
python
python test.py 2022oop
2022oop
下列说法正确的是
A. 为了美观可以在filename=test的等号边加上空格,即修改为filename = test,bash脚本仍能运行、功能不变。(左右都不能加空格)
filename=test
filename = test
8.【多选】以下说法正确的是
B. 小华git clone了一个远端项目仓库后,他在本地对仓库内一个文件脚本run.sh进行了修改,但还没通过git add run.sh将文件加入git暂存区,也没有提交新的commit。他觉得不妥,他希望放弃这次修改,他可以通过git checkout run.sh放弃本地的修改(git checkout filename指令会将工作区的指定文件的内容恢复到暂存区的状态。[git checkout filename命令的使用_酸菜。的博客-CSDN博客](https://blog.csdn.net/qq_38158479/article/details/106973979))
git clone
run.sh
git add run.sh
git
commit
git checkout run.sh
C. git branch test会创建名为test的分支并且切换到test中(不会自动切换,git checkout -b test)
git branch test
test
git checkout -b test
1.【多选】下列说法正确的是
A. std::string str("abc");和std::vector<char> str("abc");这两种对象构造方式都是可以通过编译的;(std::vector<char> str("abc");不行)
std::string str("abc");
std::vector<char> str("abc");
C. std::string类型的对象可以通过c_str()方法转化为C风格字符串,返回char*类型字符指针,并可以通过指针对字符串进行修改;(返回值为常量指针,不可更改)
std::string
c_str()
char*
2.【多选】下列说法正确的是
A. std::cout和std::endl是ostream类型的对象;(cout是对象,endl是流操作算子,可以理解为函数)
std::cout
std::endl
ostream
cout
endl
4.【多选】关于下列代码说法正确的是
#include<iostream> using namespace std; void bar(char ch, int i) { cout << "bar " << ch << ' ' << i << " "; return ; } class func { public: //(7) void operator()(char ch, int i) const { cout << "func " << ch << ' ' << i << " "; } }; template<class Pclass> void foo(char ch, int i, Pclass p) { // (6) p(ch, i); } int main() { void (*P) (char, int); // (1) P = bar(); // (2) foo('e', 13, P); // (3) auto F = func(); // (4) foo('e', 13, F); // (5) }
A. (1) 声明P是函数指针,(4) 声明F是函数对象;(F是重载了括号运算符的对象,称为函数对象)
P
F
C. (5)传参错误,(6)处foo函数Pclass只能是函数指针类型;(可以用函数对象或函数指针)
foo
Pclass
D. (7)不能把operator()设置为private成员;(会导致函数对象无法调用括号运算符)
operator()
private
5.【多选】下列关于智能指针的说法正确的是
#include <bits/stdc++.h> using namespace std; void f1(shared_ptr<int> p1) { cout << p1.use_count(); } shared_ptr<int> f2(shared_ptr<int>& p1) { f1(p1); cout << p1.use_count(); return p1; } void f3(shared_ptr<int> p2) { cout << p2.use_count(); // (1) } int main() { shared_ptr<int> p1(new int); //(2) f1(p1); //(3) cout << p1.use_count(); //(4) shared_ptr<int> p2 = f2(p1); //(5) cout << p1.use_count(); //(6) cout << p2.use_count(); //(7) f3(p1); // (8) cout << p1.use_count(); //(9) cout << p2.use_count(); //(10) return 0; }
B. 在有标号的代码中,发生拷贝构造的只有(3)(8);(5返回值有拷贝构造)
7.【多选】以下关于迭代器模式的说法正确的是:
B. 存储器类需要是迭代器类的友元。(反了,迭代器类是存储器类的友元,这样迭代器类就可以访问存储器类的私有成员)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
选择题疑难点整理
前言
最近一段时间笔者整理了2022春OOP六次作业中的选择题,从中选出了一部分题目的选项进行解析,希望能够帮助同学们提高期末复习的效率(然而事实是在整理完这篇笔记后发现自己已经彻底复习不完了/(ㄒoㄒ)/~~)
第二次作业
题1 A
A. 对于下列代码中的两个运算符重载实现:即便它们的参数均为
int
与Test
的组合,这段代码仍可以通过编译。这是因为在两个重载实现中,int
与Test
在参数中的顺序不同,编译器能够唯一地确定调用哪个运算符实现代码。运算符重载时,不必考虑可交换性和多参数类型
题3 ABC
D. (不考虑 A、B、C 选项的改动,)如果将注释
(D)
所在的行改为~Test(int data = 0){ // (D)
,该代码可以通过编译,运行输出结果为0
。析构函数不能带有参数题4 B
关于构造函数和析构函数,阅读以下可以通过编译的代码,并选出其运行输出结果:
A.
Constructing member.Constructing group.Destructing member.Destructing group.
B.
Constructing member.Constructing group.Destructing group.Destructing member.
C.
Constructing group.Constructing member.Destructing member.Destructing group.
D.
Constructing group.Constructing member.Destructing group.Destructing member.
创建和销毁的原则:创建时先成员后整体,销毁时先整体后成员,早创建的晚销毁
题5 A
B. 该代码不能通过编译,原因:
Student
类的析构函数被定义为私有成员。解决方案:将其更改为公有成员(即:将代码中注释(B)
所在的行改为public:
),方可通过编译。应该更改的是School类中的access函数权限题6 C
A. 使用
Student(int _id) {id = _id; gpa = 0.0;}
替换原代码中的Student
类构造函数(即注释(A)
所在的行)不会影响编译,因为它们的效果是完全一致的。常量只能用初始化列表定义,不能在函数体中定义B. 在
main
函数中bob
对象定义后,可以调用bob.getGpa()
,因为没有对bob
的任何成员变量作修改。常量只能调用常量函数,即使非常量函数没有更改常量数据成员,这依然是很危险的不被允许的行为D.
Student
类的getGpa
成员函数不能改为常量成员函数,因为该函数的实现中访问了非常量成员gpa
。常量成员函数可以访问变量,但不能改变变量课件中对常量、静态成员的总结表格:
题8 AD
A. 使用
new[]
构造的对象应当使用delete
释放内存,如下面代码所示。new[]要配合delete[]用第三次作业
题2 B
2.【单选】以下代码的输出是:
B) BCC 先移动构造再两次移动赋值
题3 AB
3.【多选】关于以下代码说法正确的有:
B) 如果注释15-17行,并且在12行前加explicit关键字,则第23行不可以通过编译。 explicit 关键词加入后类型转换需显式定义(L6p56)
C) 如果注释12-14行,输出结果是BA10。BAB10,还有一个浅拷贝的构造
D) 如果注释15-17行,输出结果是BA10。BA6,
c=c+3.4
c转化成int型后再调用构造函数题4 C
【单选】下面说法错误的有:
C) int a=5; int &&x=a;是合法的语句。无法将右值引用绑定到左值
题6 D
6.【单选】关于下面这段代码运行结果说法正确的有 (编译选项含有-std=c++11):
B) 输出的前4行是1\n2\n4\n5\n。 1235,按照声明的顺序而非初始化列表的顺序构造A
D) 输出中前缀是destructor的行,后面的数字按顺序是2020,2021,2021,2020,2019,2019。析构先整体后成员
题7 D
7.【单选】关于下面代码说法正确的有:
D) 如果将第12行改为class Bird: protected Animal{, 只需要去掉第29行就可以成功编译运行。protected成员无法通过对象访问
题8 ABC
8.【多选】以下说法正确的有:
A) 派生类的成员函数可以访问通过私有继承的基类的保护成员。只要是protected就可以被派生类函数访问
D) 派生类的构造函数的成员初始化列表中,可以包含基类数据成员的初始化。派生类不能直接初始化基类成员变量
第四次作业
题2 A
2.【单选】下列说法正确的是
B. 在基类中所有的纯虚函数都不必定义函数体(虚析构函数一定要定义函数体实现)
题3 BD
3.【多选】对下面代码,无法编译通过的有
题4 D
4.【单选】下列说法正确的有
A. 抽象类中一定有某个成员函数没有函数体(虚析构函数一定要有函数体)
B. 抽象类的派生类就不是抽象类了(要看有没有重写覆盖)
C. 只有当一个抽象类的派生类中将该抽象基类的所有纯虚函数都重写覆盖,该派生类才不再是抽象类(析构函数会自动生成,不需要手动重写覆盖)
题5 B
5.【单选】关于类型转换,说法正确的有
A. 若Derived是Base的派生类,p为Base类的指针,指向了Derived的对象,则dynamic_cast<Derived*>(p)就可以正确返回Derived的指针(前提是Base和Derived有虚函数关系)
D. dynamic_cast只能用于向下类型转换(dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting),只是向上类型转换十分安全一般不用调用这个函数)
题6 AB
6.【多选】关于多态,下面说法正确的是
C. 指针、引用对虚函数的调用总是晚绑定,即运行时绑定(p->Base::func()通过类名可以强制早绑定)
题7 D
7.【单选】关于下面代码,说法正确的是
C. (3) 处的返回值为2,第二个参数1.2被强制类型转换成了 int 类型(需要强制类型转换,否则编译器会认为找不到符合(int,float)参数类型的函数)
第五次作业
题1 E
1.【单选】请阅读或执行以下代码,下列说法正确的是
B.
choiceB()
中(2)处不能调用ComputerScience::setStudentNumber
,因为命名空间THU
将命名空间ComputerScience
隐藏了,只声明命名空间THU
无法使用命名空间ComputerScience
中的函数(namespace无重写隐藏功能)E.
choiceE()
可正常编译运行,其中的三个using
声明是合法的(只要最后using的是同一个东西就不会报错)题2 CE
2.【多选】请阅读或执行以下代码,下列说法正确的是
E.
choiceE()
会出现编译错误或运行异常(不同维数的tuple不能相互转换)题3 C
3.【单选】请阅读或执行以下代码,下列说法正确的是
A.
choiceA()
可正常编译运行,(1)处输出1 5
(end指向最后一个元素的下一个位置)B.
choiceB()
可正常编译运行,(2)处输出3
(erase函数返回的是删除元素的下一个元素的迭代器)D. 对于
choiceD()
,如果删去函数operator <<
,(4)处的<<
将调用vector
的默认重载流运算符方法(vector未默认重载流运算符)题4 AE
4.【多选】请阅读或执行以下代码,下列说法正确的是
B.
choiceB()
中可以修改传入lst
中的第2个位置上的元素(约定lst.begin()
是指向第0个位置的迭代器)(list无法通过下标方式访问)E.
choiceE()
中(3)处会出现运行错误,因为erase
操作使得迭代器result
失效(listl类型插入和删除操作不会导致迭代器失效(除指向被删除的元素的迭代器外))题5 AC
5.【多选】请阅读或执行以下代码,下列说法正确的是
D.
choiceD()
中(6)处的输出是1
(2,保留了首尾,erase函数遵循左闭右开原则)E.
choiceE()
的输出是Sunday Monday Tuesday Wednesday Thursday Friday Saturday
,以换行符结尾。(每添加一个元素会根据首元素的字符串的字典序顺序重新排序)题7 BC
7.【多选】阅读以下代码(linux环境下保存为
main.sh
)同目录下的
test.py
为这个
python
脚本的意义为打印传递给脚本的一个参数,例如python test.py 2022oop
,其执行结果为输出2022oop
。下列说法正确的是
A. 为了美观可以在
filename=test
的等号边加上空格,即修改为filename = test
,bash脚本仍能运行、功能不变。(左右都不能加空格)题8 BD
8.【多选】以下说法正确的是
B. 小华
git clone
了一个远端项目仓库后,他在本地对仓库内一个文件脚本run.sh
进行了修改,但还没通过git add run.sh
将文件加入git
暂存区,也没有提交新的commit
。他觉得不妥,他希望放弃这次修改,他可以通过git checkout run.sh
放弃本地的修改(git checkout filename指令会将工作区的指定文件的内容恢复到暂存区的状态。[git checkout filename命令的使用_酸菜。的博客-CSDN博客](https://blog.csdn.net/qq_38158479/article/details/106973979))C.
git branch test
会创建名为test
的分支并且切换到test
中(不会自动切换,git checkout -b test
)第六次作业
题1 BD
1.【多选】下列说法正确的是
A.
std::string str("abc");
和std::vector<char> str("abc");
这两种对象构造方式都是可以通过编译的;(std::vector<char> str("abc");
不行)C.
std::string
类型的对象可以通过c_str()
方法转化为C风格字符串,返回char*
类型字符指针,并可以通过指针对字符串进行修改;(返回值为常量指针,不可更改)题2 BCD
2.【多选】下列说法正确的是
A.
std::cout
和std::endl
是ostream
类型的对象;(cout
是对象,endl
是流操作算子,可以理解为函数)题4 ABD
4.【多选】关于下列代码说法正确的是
A. (1) 声明
P
是函数指针,(4) 声明F
是函数对象;(F是重载了括号运算符的对象,称为函数对象)C. (5)传参错误,(6)处
foo
函数Pclass
只能是函数指针类型;(可以用函数对象或函数指针)D. (7)不能把
operator()
设置为private
成员;(会导致函数对象无法调用括号运算符)题5 ACD
5.【多选】下列关于智能指针的说法正确的是
B. 在有标号的代码中,发生拷贝构造的只有(3)(8);(5返回值有拷贝构造)
题7 AD
7.【多选】以下关于迭代器模式的说法正确的是:
B. 存储器类需要是迭代器类的友元。(反了,迭代器类是存储器类的友元,这样迭代器类就可以访问存储器类的私有成员)
The text was updated successfully, but these errors were encountered: