c++ 复习 第七章 继承与派生

派生类的定义

多继承:派生类同时有多个基类

class 派生类名: 继承方式1 基类名1,继承方式2 基类名2{ 成员声明; }

继承方式默认为private

派生类的生成过程

  • 吸收基类成员
    这步之后,派生类就包含了所有基类中除了构造和析构函数之外的所有成员
  • 改造基类成员
    访问控制:继承方式
    声明一个和某基类成员同名的新成员:隐藏或者覆盖
  • 添加新成员

派生访问属性

我现在的理解大概就是,无论你是哪种方法继承,基类的私有成员都在派生类中作为一个独一无二的存在(既不是public 也不是 private 成员)然后公有继承就把基类中除了private成员的其他成员变为派生类中的public ,私有继承就把基类中除了private成员的其他成员变为派生类中的private。至于派生类中对象或者成员函数的访问,就和正常的类一样。那个基类中的私有成员则是一个特殊的存在,需要单独搞。

题目

  1. 派生类将其本身与基类区别开来的方法是( )。
    A、添加新成员
    B、使用公有继承
    C、使用虚基类
    D、使用多继承

A

  1. class XX{
    int xdata;
    public:
    XX(int n=0) : xdata (n) { }
    };
    class YY : public XX{
    int ydata;
    public:
    YY(int m=0, int n=0) : XX(m), ydata(n) { }
    };
    则YY类的对象包含的数据成员的个数是( )。
    A、1
    B、2
    C、3
    D、4

B
这里应该是这样的:虽然是public继承,但是数据成员依旧是都被继承了,不过是当public继承时,不能直接访问到private成员而已

3.下列描述中,错误的是( )。
A公有继承时基类中的公有成员在派生类中仍是公有成员
B公有继承时基类中的保护成员在派生类中仍是保护成员
C保护继承时基类中的公有成员在派生类中仍是公有成员
D保护继承时基类中的保护成员在派生类中仍是保护成员

C
注意:公有继承将基类的public和protect保持不变,注意是保持不变,而不是变成派生类中的public
但是protect继承和private继承都是将基类中的public和protect变成protect或者private

  1. 在多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则( )。
    A、完全相同
    B、完全不同
    C、部分相同
    D、以上都不对

A

  1. 下列关于派生类和基类的描述中,正确的是( )。
    A、派生类成员函数只能访问基类的公有成员
    B、派生类对基类的默认继承方式是公有继承
    C、派生类成员函数可以访问基类的所有成员
    D、派生类成员函数只能访问基类的公有和保护成员

D
解释见上面对于访问属性的解释

6.已知B类是A类的公有派生类,且有定义:A a, *p1; B b, *p2=&b;,则下列选项中属于非法操作的是( )。
A b=a;
B p1=&b;
C A &a2=b;
D p1=p2;

A
根据类型兼容规则:
一公有派生类对象在使用上可以被当作基类的对象,反之不可以。这表现在:
1.派生类的对象可以隐含转化为基类对象
2.派生类的对象可以初始化基类的引用
3.派生类的指针可以隐含转化为基类的指针
通过基类对象名,指针只能使用从基类继承的成员

对于本题:
A a, *p1; B b, *p2=&b;
b=a用一个基类对象初始化一个派生类对象,显然不对
p1=&b;用一个派生类指针初始化一个基类指针,可以
A &a2=b;用派生类初始化基类的引用,可以
p1=p2;用派生类指针初始化基类指针,可以

7.下列关于赋值兼容性规则的描述中,错误的是( )。
A、不要求派生类的派生方式
B、派生类的对象可以赋给基类对象
C、派生类的对象可以初始化基类的引用
D、派生类的对象的地址可以赋给基类类型的指针

A
赋值兼容规则都是基于公有派生类的

8.

这题很不错
写出下面程序的输出


#include  
using namespace std; 
class A {
    public:
        int a;
        A(int x=0) { a=x; cout<<"调用构造函数A"<<a<<endl; }
        ~A() { cout<<"调用析构函数A"<<endl; }
};
class B:public A {
    public:
        int a;
        B(int x=5) { a=x; cout<<"调用构造函数B"<<a<<endl; }
        ~B() { cout<<"调用析构函数B"<<endl; }
};
int main() {
    A *p=new B;
    cout<<"a="<<p->a<<endl;
    return 0;
}

解释一下
主程序中
A *p=new B;
这个new B,就是分配一个B大小的内存空间呗,理解为默认构造一个B类型的对象,那么就调用构造函数,首先调用基类A的构造函数,数据成员a被赋值为0,因此输出调用构造函数A0
然后调用派生类的构造函数,输出
调用构造函数B5
然后因为A *p=new B;是用派生类指针初始化基类指针是,因此p->a基类中的数据成员a,为0
因此输出
a=0

此外,值得注意的一点是,这个程序并不输出析构函数的内容,这个

你可能感兴趣的:(面向对象程序设计实验,c++,开发语言,后端)