目录
一、概念题
-
下面哪种面向对象的方法可以让你变得富有()。
A、继承 B、封装 C、多态 D、抽象
-
()是面向对象程序设计语言中的一种机制,这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联到具体的对象。
A、继承 B、模板 C、对象的自身引用 D、动态绑定
-
面向对象设计中的继承和组合,下面说法错误的是()。
A、继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用
B、组合的对象不需要关心各自的实现细节,之间的关系是在运行时才确定的,是一种动态复用,也称为黑盒复用
C、优先使用继承,而不是组合,是面向对象设计的第二原则
D、继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏父类的封装性的表现
-
以下关于纯虚函数的说法,正确的是()。
A、声明纯虚函数的类不能实例化对象
B、声明纯虚函数的类是虚基类
C、子类必须实现基类的纯虚函数
D、纯虚函数必须是空函数
-
关于虚函数的描述正确的是()。
A、派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B、内联函数不能是虚函数
C、派生类必须重新定义基类的虚函数
D、虚函数可以是一个 static 型的函数
-
关于虚表说法正确的是()。
A、一个类只能有一个虚表
B、基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
C、虚表是在运行期间动态生成的
D、一个类的不同对象共享该类的虚表
-
假设 A 类中有虚函数,B 继承自 A,B 重写 A 中的虚函数,也没有定义任何虚函数,则()。
A、A 类对象的前 4 个字节存储虚表地址,B 类对象的前 4 个字节不是虚表地址
B、A 类对象和 B 类对象的前 4 个字节存储的都是虚基表的地址
C、A 类对象和 B 类对象的前 4 个字节存储的虚表地址相同
D、A 类和 B 类虚表中虚函数个数相同,但 A 类和 B 类使用的不是同一张虚表
参考答案:
-
A
-
D
-
C
-
A
-
B
-
内联函数不能是虚函数。因为内联函数是一个静态行为(编译器在预处理阶段将内联函数的函数体替换到函数调用处),而虚函数是一个动态行为(编译器并不知道要调用的是基类的虚函数,还是派生类的虚函数),它们之间是存在矛盾的。
我们之所以能看到一些像内联函数的虚函数,是因为某个函数是否是内联函数是由编译器决定的,我们只能向编译器建议某个函数可以是内联函数,但编译器有自己的判断法则。
-
静态成员函数不能是虚函数。因为静态成员函数没有 this 指针,而对于虚函数,它的调用恰恰是使用了 this 指针(在有虚函数的类实例中,this 指针调用虚函数表指针,在虚函数表中找到需要调用的虚函数地址)。
-
-
D
基类和派生类不共用同一张虚表,同一类的不同对象共用同一张虚表。
#include <iostream> using namespace std; class A { public: virtual inline void func() { cout << "A::func" << endl; } protected: int _a = 1; }; class B : public A { protected: int _b = 2; }; int main() { A a; B b1; B b2; return 0; }
-
D
二、程序题
-
下面程序输出结果是什么?
#include<iostream> using namespace std; class A { public: A(const char* s) { cout << s << endl; } ~A() { } }; class B : virtual public A { public: B(const char* s1, const char* s2) : A(s1) { cout << s2 << endl; } }; class C : virtual public A { public: C(const char* s1, const char* s2) : A(s1) { cout << s2 << endl; } }; class D : public B, public C { public: D(const char* s1, const char* s2, const char* s3, const char* s4) : B(s1, s2), C(s1, s3), A(s1) { cout << s4 << endl; } }; int main() { D* p = new D("class A", "class B", "class C", "class D"); delete p; return 0; }
A、
class A class B class C class D
B、
class D class B class C class A
A、
class D class C class B class A
A、
class A class C class B class D
-
(多继承中指针偏移问题)下面说法正确的是()。
class Base1 { public: int _b1; }; class Base2 { public: int _b2; }; class Derive : public Base1, public Base2 { public: int _d; }; int main() { Derive d; Base1* p1 = &d; Base2* p2 = &d; Derive* p3 = &d; return 0; }
A、
p1 == p2 == p3
B、p1 < p2 < p3
C、p1 == p3 != p2
D、p1 != p2 != p3
-
下面程序输出结果是什么?
#include <iostream> class A { public: virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; } virtual void test() { func(); } }; class B : public A { public: void func(int val = 0) { std::cout << "B->" << val << std::endl; } }; int main() { B* p = new B; p->test(); return 0; }
A、
A->0
B、B->1
C、A->1
D、B->0
E、编译错误 F、以上都不正确
参考答案:
-
A
-
C
-
B