裸考精选题目
以下题目均为不定项选择题,快来试试吧!
1.有如下程序:
#include<iostream>
using namespace std;
class Power
{
public:
Power(int x) :val(x) {}
________
protected:
int val;
};
class Square :public Power
{
public:
Square(int x) :Power(x) {}
void Display() { cout << val << "的平方是" << val * val << endl; }
};
int main()
{
Power*p = new Square(3);
p->Display();
delete p;
return 0;
}
若运行时的输出结果为“3的平方是9”,则划线处缺失的语句可能是______。
- A.void Display(){}
- B.virtual void Display()=0;
- C.void virtual Display()=0;
- D.void Display() virtual {}
- E.virtual void Display(){}
2.有如下程序:
#include <iostream>
using namespace std;
class TestClass
{
int n;
public:
TestClass(int k):n(k) {}
int get() { return n; }
int get() const { return n + 1; }
};
int main()
{
TestClass p(5);
const TestClass q(6);
cout<< p.get() << q.get();
return 0;
}
执行后的输出结果是______。(不如当成填空题吧~~~)
- A.55
- B.56
- C.57
- D.66
- E.67
3.有如下四个语句:
cout << 'A' << setfill('*') << left << setw(7) << 'B' << endl; // 1
cout << setfill('*') << left << setw(7) << 'A' << 'B' << endl; // 2
cout << 'A' << setfill('*') << right << setw(7) << 'B' << endl; // 3
cout << setfill('*') << right << setw(7) << 'A' << 'B' << endl; // 4
其中能显示A******B的是______。(这道题为拓展题,可以不看)
- A.①和③
- B.①和④
- C.②和③
- D.②和④
4.有如下程序:
#include <iostream>
using namespace std;
class Con
{
char ID;
public:
Con() : ID('A'){cout << 1;}
Con(char ID) : ID(ID) { cout << 2; }
Con(Con&c) : ID(c.getID()) { cout << 3; }
char getID() const { return ID; }
};
void show(Con c) { cout << c.getID(); }
int main()
{
Con c1;
show(c1);
Con c2('B');
show(c2);
return 0;
}
执行上面程序的输出结果是______。
- A.13A23B
- B.23A33B
- C.1A2B
- D.2A3B
5.有如下程序:
#include <iostream>
using namespace std;
class Basel
{
public:
Basel(int d) { cout << d; }
~Basel() {}
};
class Base2
{
public:
Base2(int d) { cout << d; }
~Base2() {}
};
class Derived : public Basel, Base2
{
public:
Derived(int a, int b, int c, int d) :Basel(b), Base2(a), b1(d), b2(c) {}
private:
int b1;
int b2;
};
int main()
{
Derived d(1, 2, 3, 4);
return 0;
}
执行这个程序的输出结果是______。
- A.1234
- B.2134
- C.12
- D.21
6.下列关于goto语句的描述中,正确的是______。
- A.goto语句可在一个文件中随意转向
- B.goto语句后面要跟一个它所转向的语句
- C.goto语句可以同时转向多条语句
- D.goto语句可以从一个循环体内转到循环体外
7.有如下类定义:
class AA
{
int a;
public:
int *getRef() const {return &a;} // 1
int getValue() const {return a;} // 2
void setRef(int n) const {a = n;} // 3
const void setValue(int n) {a = n;} // 4
friend void show(AA aa) const {cout << a;} // 5
};
其中四个函数的定义中正确的有______。
- A.①
- B.②
- C.③
- D.④
- E.⑤
8.有如下程序:
#include <iostream>
using namespace std;
int s = 0;
class sample
{
static int n;
public:
sample(int i)
{
n = i;
}
static void add()
{
s += n;
}
};
int sample::n = 0;
int main()
{
sample a(2), b(5);
sample::add();
cout << s << endl;
return 0;
}
程序运行后的输出结果是______。
- A.2
- B.5
- C.7
- D.3
9.下列关于this指针的描述中,正确的是______。
- A.类的成员函数都有this指针
- B.类的友元函数都有this指针
- C.任何与类相关的函数都有this指针
- D.类的非静态成员函数都有this指针
10.有如下程序:
#include <iostream>
using namespace std;
class TestClass
{
public:
void who() { cout << "TestClass" << endl; }
};
class TestClass1 :public TestClass
{
public:
void who() { cout << "TestClass1" << endl; }
};
int main()
{
TestClass *p;
TestClass1 obj1;
p = &obj1;
p -> who();
return 0;
}
则该程序运行后的输出结果是______。
- A.TestClass1
- B.TestClass
- C.0
- D.报错
11.下列关于纯虚函数与抽象类的描述中,错误的是______。
- A.纯虚函数是一种特殊的虚函数,它没有具体的实现
- B.抽象类是指具有纯虚函数的类
- C.一个基类声明了纯虚函数,该基类的派生类一定不是抽象类
- D.抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出
涉及知识点复习
运算符重载
重载原则
- 除了类属关系运算符"."、成员指针运算符".*"、作用域运算符"::"、sizeof运算符和三目运算符"?:"以外,C++中的所有运算符都可以重载。
- 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
- 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
- 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
- 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
- 运算时,有数和对象的混合运算时,必须使用友元
- =,(),[],->不能以友元方式重载
- 二元运算符中,第一个操作数为非对象时,必须使用友元函数。如输入输出运算符<<和>>
虚函数
概念
在函数前面加virtual,就是虚函数
- 只有成员函数才可定义为虚函数,友元/全局/static/构造函数都不可以
- 虚函数需要在函数名前加上关键字virtual
- 成员函数如果不是虚函数,其解析过程发生在编译时而非运行时
- 派生类可以不覆盖(重写)它继承的虚函数
override关键字
override关键字放在派生类的虚函数后,如果编译器发现派生类重写的虚函数与基类的虚函数不一样(参数或其他不一样的地方),那么编译器将报错
- 父类的虚函数不可使用
- 放在子类虚函数的参数列表后(如果函数有尾指返回类型,那么要放在尾指返回类型后),用来说明此函数为覆盖(重写)父类的虚函数。如果类方法在类外进行定义,那么override不能加
- 不一定强制要求子类声明这个关键字,但是建议使用
- 这是C++11标准填入的
final关键字
如果我们定义的一个虚函数不想被派生类覆盖(重写),那么可以在虚函数之后添加一个final关键字,声明这个虚函数不可以被派生类所覆盖(重写)
构造函数为什么不能为虚函数?析构函数为什么要虚函数?
构造函数不定义为虚函数的原因:
(1)创建一个对象时需要确定对象的类型,而虚函数是在运行时动态确定其类型的。在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型
(2)虚函数的调用需要虚函数表指针vptr,而该指针存放在对象的内存空间中,若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表vtable地址用来调用虚构造函数了
(3)虚函数的作用在于通过父类的指针或者引用调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类或者引用去调用,因此就规定构造函数不能是虚函数
析构函数一般定义为虚函数的原因:
简单来说,C++基类采用virtual虚析构函数是为了防止内存泄漏。
具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。
所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数
纯虚函数
语法:virtual 返回值类型 函数名(参数列表)=0,当类中有了纯虚函数,这个类也称为抽象类。
抽象类特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
自定义字符串的实现
#include <iostream>
#include <cstring>
using namespace std;
class MyString{
public:
MyString(const char *s = nullptr){
if (s) {
str_ = new char[strlen(s) + 1];
strcpy(str_,s);
}
else {
str_ = new char[1];
*str_ = '\0';
}
}
MyString(const MyString& s) : str_(new char[s.len_ + 1]),len_(s.len_){
strcpy(str_, s.str_);
}
~MyString(){
delete[] str_;
}
MyString& operator = (const MyString& s){
if (this != &s)//避免自身赋值
{
delete[] str_;
str_ = new char[strlen(s.str_) + 1];
strcpy(str_, s.str_);
}
return *this;
}
char* c_str() const {
return str_;
}
private:
char *str_;
int len_;
};
ostream& operator << (ostream& os, const MyString& s){
os << s.c_str();
return os;
}
参考答案
1
答案:B.C.E
注意:void virtual 和 virtual void 没有区别,但是不能放在函数名末尾
2
答案:C
思考:删除get函数后,结果又是什么呢?
int get() { return n; }
3
答案:C
4
答案:A
思考:改变show函数为如下,结果又是什么呢?
void show(Con &c) { cout << c.getID(); }
5
答案:D
思考:改变继承顺序,结果又是什么呢?
class Derived : public Base2, Base1
6
答案:D
[解析] goto语句也可以跳出循环和switch语句,goto语句无条件地转移程序的执行控制。它总是与一标号相匹配,其形式为:goto标号;,标号是用户自定义的标识符,它可以处于goto语句的前面,也可以处于其后,但标号必须与goto语句处于同一个函数中。定义标号时,由一个标识符后面跟一个冒号组成。
7
答案:B.D
思考:错误的语句应该怎么改呢?答案如下
const int *getRef() const {return &a;} //1
void setRef(int n) {a = n;} //3
friend void show(AA aa) {cout << aa.a;} //5,注意改了两处
8
答案:B
9
答案:D
10
答案:B
11
答案:C