【笔试题】【day14】

目录

第一题(哪些成员变量需要在初始化列表初始化)

第二题(多态的条件)

第三题(多态的条件(通过父类对象调用的全部都是父类的方法))

第四题(菱形继承,虚拟继承的初始化顺序)


第一题(哪些成员变量需要在初始化列表初始化)

有一个类B继承自类A,他们数据成员如下:

class A {
    ...
private:
    int a;
};
class B : public A {
    ...
private:
    int a;
public:
    const int b;
    A &c;
    static const char* d;
    B* e;
}

则构造函数中,成员变量一定要通过初始化列表来初始化的是

A a b c
B b c e
C b c d e
D c e
E b d
F b c

哪些成员必须在初始化列表的位置初始化?

1.const修饰的成员变量(常量数据是不允许修改的,所以只能通过参数列表初始化)

2.引用类型的成员变量(引用不能为空,必须要引用一个对象)

3.类的类型对象,该类没有默认的构造函数。(比方说我们的B类中没有默认构造函数,有一个B(int x)的构造函数,那么我们的另外一个类A去调用我们这个类B的时候,就必须在初始化列表的位置初始化这个B)

A()
    :B(30)
{
 
}

【笔试题】【day7】_桜キャンドル淵的博客-CSDN博客

中的第四题

但是这里的d也是const的呀,需不需要在参数列表的位置初始化?

静态成员不能再类的内部初始化!

因为静态的成员的初始化必须要放在类的外面,使用类访问限定符指明。

F

第二题(多态的条件)

class Base {
public:
    Base(int j): i(j) {}
    virtual~Base() {}
    void func1() {
        i *= 10;
        func2();
    }
    int getValue() {
        return i;
    }
protected:
    virtual void func2() {
        i++;
    }
protected:
        int i;
};
class Child: public Base {
public:
    Child(int j): Base(j) {}
    void func1() {
        i *= 100;
        func2();
    }
protected:
    void func2() {
        i += 2;
    }
};
int main() {
    Base * pb = new Child(1);
    pb->func1();
    cout << pb->getValue() << endl; delete pb;
}

A 11
B 101
C 12
D 102

这里我们的Base *pd=new Child(1)

会调用子类的Child的构造函数,

 在子类的构造的过程中,其初始化列表中会构造一个Base(j)

 这里的Base(j)又会初始化i为j,所以我们此时的i为1

然后pb->func1()

由于我们的pb是父类的指针,指向的是子类的对象,但是我们的fun1再Base前面并没有加上virtual,所以不构成多态!所以这里还是按照父类的指针就调用父类的方法

 此时我们的i*=10,变成了10,然后调用func2函数

但是我们观察到这个func2函数基类有virtual,并且这是一个父类指针,指向子类,满足多态的条件,所以这里构成多态,也就是调用子类的func2函数,也就是我们下面的这个func2(),所以我们的i+=2变成了12

 

C

第三题(多态的条件(通过父类对象调用的全部都是父类的方法))

#include<iostream>
#include<string>
using namespace std;
class B0 {
public:
    virtual void display() {
        cout << "B0::display0" << endl;
    }
};
class B1 :public B0 {
public:
    void display() { cout << "B1::display0" << endl; }
};
class D1 : public B1 {
public:
    void display() {
        cout << "D1::display0" << endl;
    }
};
void fun(B0 ptr) {
    ptr.display();
}
int main() {
    B0 b0;
    B1 b1;
    D1 d1;
    fun(b0);
    fun(b1);
    fun(d1);
}

A B0::display0 B0::display0 B0::display0
B B0::display0 B0::display0 D1::display0
C B0::display0 B1::display0 D1::display0
D B0::display0 B1::display0 B1::display0

这里我们观察到我们的fun()是一个全局函数

然后我们传入的对象都会被赋值给一个父类对象B0

然后再用这个父类对象去调用display()函数

这里不满足我们多态的条件,只是静态编译,所以我们输出的三个全部都是B0::display0

(对象的调用是静态编译!不是多态)

 

第四题(菱形继承,虚拟继承的初始化顺序)

#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


C class D
class C
class B

class A


D class A
class C
class B
class D

我们这里的初始化的顺序是按照这里继承的顺序来的,首先我们继承了B类

 但是我们的B类中又需要有一个A类,A类的构造又需要有一个字符串,所以上面的s1就是我们A类的构造函数中的字符串也就是classA最先被打印出来

然后构造B,打印classB

然后构造C,因为我们的C这里是虚拟继承的,并不会再去构造一个A,而是直接和B共用同一个A。打印classC 

最后打印构造D类,打印classD

A

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桜キャンドル淵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值