#872. 面向对象练习
面向对象练习
一、选择题
1.下列关于类的说法,错误的是( )。
{{ select(1) }}
- 构造函数不能声明为虚函数,但析构函数可以
- 函数参数如声明为类的引用类型,调用时不会调用该类的复制构造函数
- 静态方法属于类而不是某个具体对象,因此推荐用 类名::方法(...) 调用
- 不管基类的析构函数是否是虚函数,都可以通过基类指针/引用正确删除派生类对象
2.假设变量 veh 是类 Car 的一个实例,我们可以调用 veh.move(),是因为面向对象编程有( )性质。
class Vehicle {
private:
string brand;
public:
Vehicle(string b) : brand(b) {}
void setBrand(const string& b) { brand = b; }
string getBrand() const { return brand; }
void move() const {
cout << brand << " is moving..." << endl;
}
};
class Car : public Vehicle {
private:
int seatCount;
public:
Car(string b, int seats) : Vehicle(b), seatCount(seats) {}
void showInfo() const {
cout << "This car is a " << getBrand()
<< " with " << seatCount << " seats." << endl;
}
};
{{ select(2) }}
- 继承
- 封装
- 多态
- 链接
3.下面代码中 v1 和 v2 调用了相同接口 move(),但输出结果不同,这体现了面向对象编程的( )特性。
class Vehicle {
private:
string brand;
public:
Vehicle(string b) : brand(b) {}
void setBrand(const string& b) { brand = b; }
string getBrand() const { return brand; }
virtual void move() const {
cout << brand << " is moving..." << endl;
}
};
class Car : public Vehicle {
private:
int seatCount;
public:
Car(string b, int seats) : Vehicle(b), seatCount(seats) {}
void showInfo() const {
cout << "This car is a " << getBrand()
<< " with " << seatCount << " seats." << endl;
}
void move() const override {
cout << getBrand() << " car is driving on the road!" << endl;
}
};
class Bike : public Vehicle {
public:
Bike(string b) : Vehicle(b) {}
void move() const override {
cout << getBrand() << " bike is cycling on the path!" << endl;
}
};
int main() {
Vehicle* v1 = new Car("Toyota", 5);
Vehicle* v2 = new Bike("Giant");
v1->move();
v2->move();
delete v1;
delete v2;
return 0;
}
{{ select(3) }}
- 继承 (Inheritance)
- 封装 (Encapsulation)
- 多态 (Polymorphism)
- 链接 (Linking)
4.关于虚函数描述错误的是( )。
{{ select(4) }}
- 虚函数用于支持运行时多态
- 通过基类指针调用虚函数会根据对象实际类型决定调用版本
- 构造函数可以声明为虚函数
- 基类析构函数常声明为虚函数以避免资源泄漏
5.执行如下代码,会输出 钢琴:叮咚叮咚 和 吉他:咚咚当当 。这体现了面向对象编程的( )特性。
class Instrument {
public:
virtual void play() {
cout << "乐器在演奏声音" << endl;
}
virtual ~Instrument() {}
};
class Piano : public Instrument {
public:
void play() override {
cout << "钢琴:叮咚叮咚" << endl;
}
};
class Guitar : public Instrument {
public:
void play() override {
cout << "吉他:咚咚当当" << endl;
}
};
int main() {
Instrument* instruments[2];
instruments[0] = new Piano();
instruments[1] = new Guitar();
for (int i = 0; i < 2; ++i) {
instruments[i]->play();
}
for (int i = 0; i < 2; ++i) {
delete instruments[i];
}
return 0;
}
{{ select(5) }}
- 继承
- 封装
- 多态
- 链接
6.关于以下代码,说法正确的是( )。
class Instrument {
public:
void play() {
cout << "乐器在演奏声音" << endl;
}
virtual ~Instrument() {}
};
class Piano : public Instrument {
public:
void play() override {
cout << "钢琴:叮咚叮咚" << endl;
}
};
class Guitar : public Instrument {
public:
void play() override {
cout << "吉他:咚咚当当" << endl;
}
};
int main() {
Instrument* instruments[2];
instruments[0] = new Piano();
instruments[1] = new Guitar();
for (int i = 0; i < 2; ++i) {
instruments[i]->play();
}
for (int i = 0; i < 2; ++i) {
delete instruments[i];
}
return 0;
}
{{ select(6) }}
- 执行代码会输出两行,内容分别为:
钢琴:叮咚叮咚和吉他:咚咚当当 - 执行代码会输出两行,内容分别为:
乐器在演奏声音和乐器在演奏声音 - 代码编译出现错误
- 代码运行出现错误
7.下列关于 C++ 中类的描述,正确的是( )。
{{ select(7) }}
- 如果类没有用户声明的构造函数,那么编译器会隐式声明一个默认构造函数
- 类的析构函数可以被重载,一个类可以有多个析构函数
- 类中的所有成员都必须声明为 public
- 类和结构体在 C++ 中没有区别,包括默认访问权限也相同
二、判断题
8.以下代码中,构造函数被调用的次数是1次。
class Test {
public:
Test() { cout << "T "; }
};
int main() {
Test a;
Test b = a;
}
{{ select(8) }}
- 正确
- 错误
9.当基类可能被多态使用,其析构函数应该声明为虚函数。
{{ select(9) }}
- 正确
- 错误
10.面向对象编程中,封装是指将数据和操作数据的方法绑定在一起,并对外隐藏实现细节。
{{ select(10) }}
- 正确
- 错误
11.下面定义了一个表示二维坐标点的类 Point , 并提供了一个带参数的构造函数,但第 ② 行 Point b; 会调用编译器自动生成的默认构造函数,将 b.x 和 b.y 被初始化为 0.0,程序可以正常编译运行。
class Point {
public:
double x, y;
Point(double px, double py) : x(px), y(py) {}
void print() {
cout << "(" << x << ", " << y << ")";
}
};
int main() {
Point a(3.0, 4.0); // ①
Point b; // ②
a.print();
}
{{ select(11) }}
- 正确
- 错误
12.C++ 中的继承支持单继承和多继承,但子类无法直接访问父类的私有成员。
{{ select(12) }}
- 正确
- 错误