写作网站都有哪些ppp,网站上那些兼职网页怎么做,定制软件系统,网站双域名✍个人博客#xff1a;Pandaconda-CSDN博客 #x1f4e3;专栏地址#xff1a;http://t.csdnimg.cn/fYaBd #x1f4da;专栏简介#xff1a;在这个专栏中#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话#xff0c;欢迎点赞#x1f44d;收藏Pandaconda-CSDN博客 专栏地址http://t.csdnimg.cn/fYaBd 专栏简介在这个专栏中我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话欢迎点赞收藏您的支持就是我创作的最大动力 16. 什么是虚拟继承
由于 C 支持多继承除了 public、protected 和 private 三种继承方式外还支持虚拟virtual继承举个例子
#include iostream
using namespace std;class A{}
class B : virtual public A{};
class C : virtual public A{};
class D : public B, public C{};int main()
{cout sizeof(A) sizeof A endl; // 1空对象只有一个占位cout sizeof(B) sizeof B endl; // 4一个bptr指针省去占位不需要对齐cout sizeof(C) sizeof C endl; // 4一个bptr指针省去占位不需要对齐cout sizeof(D) sizeof D endl; // 8两个bptr省去占位不需要对齐
}
上述代码所体现的关系是B 和 C 虚拟继承 AD 又公有继承 B 和 C这种方式是一种菱形继承或者钻石继承可以用如下图来表示 虚拟继承的情况下无论基类被继承多少次只会存在一个实体。虚拟继承基类的子类中子类会增加某种形式的指针或者指向虚基类子对象或者指向一个相关的表格表格中存放的不是虚基类子对象的地址就是其偏移量此类指针被称为 bptr如上图所示。如果既存在 vptr 又存在 bptr某些编译器会将其优化合并为一个指针。
没有虚继承
// 间接基类A
class A{
protected:int m_a;
};
// 直接基类B
class B: public A{
protected:int m_b;
};
// 直接基类C
class C: public A{
protected:int m_c;
};
// 派生类D
class D: public B, public C{
public:void seta(int a){//m_a a; //命名冲突A::m_a a; //命名不再冲突}void setb(int b){m_b b; //正确}void setc(int c){m_c c; //正确} void setd(int d){m_d d; //正确}
private:int m_d;
};
int main(){D d;return 0;
}
有虚继承
// 间接基类A
class A{
protected:int m_a;
};
// 直接基类B
class B: virtual public A{
protected:int m_b;
};
// 直接基类C
class C: virtual public A{
protected:int m_c;
};
//派生类D
class D: public B, public C{
public:void seta(int a){m_a a; //正确}void setb(int b){m_b b; //正确}void setc(int c){m_c c; //正确} void setd(int d){m_d d; //正确}
private:int m_d;
};
17. 哪些函数不能是虚函数把你知道的都说一说 构造函数构造函数初始化对象派生类必须知道基类函数干了什么才能进行构造当有虚函数时每一个类有一个虚表每一个对象有一个虚表指针虚表指针在构造函数中初始化。 内联函数内联函数表示在编译阶段进行函数体的替换操作而虚函数意味着在运行期间进行类型确定所以内联函数不能是虚函数。 静态函数静态函数不属于对象属于类静态成员函数没有 this 指针因此静态函数设置为虚函数没有任何意义。 友元函数友元函数不属于类的成员函数不能被继承。对于没有继承特性的函数没有虚函数的说法。 普通函数普通函数不属于类的成员函数不具有继承特性因此普通函数没有虚函数。 模板函数每个含有虚函数的类中都有一个虚函数表该虚函数表存储着该类的所有的虚函数的地址。然而当虚函数为模板函数时由于编译阶段无法确定类的虚函数表的大小因此编译器禁止这种用法。这是因为编译器在编译一个文件时并不知道其他文件对该类的虚函数的调用情况所以无法确定模板虚函数的实例化个数。
18. 什么是纯虚函数与虚函数的区别
纯虚函数首先是虚函数其次它没有函数体取而代之的是用 “0”。
既然是虚函数它的函数指针会被存在虚函数表中由于纯虚函数并没有具体的函数体因此它在虚函数表中的值就为 0而具有函数体的虚函数则是函数的具体地址。
一个类中如果有纯虚函数的话称其为抽象类。抽象类不能用于实例化对象否则会报错。抽象类一般用于定义一些公有的方法。子类继承抽象类也必须实现其中的纯虚函数才能实例化对象。
举个例子
#include iostream
using namespace std;class Base
{
public:virtual void fun1(){cout 普通虚函数 endl;}virtual void fun2() 0;virtual ~Base() {}
};class Son : public Base
{
public:virtual void fun2() {cout 子类实现的纯虚函数 endl;}
};int main()
{Base* b new Son;b-fun1(); //普通虚函数b-fun2(); //子类实现的纯虚函数return 0;
} 虚函数和纯虚函数区别 虚函数是为了实现动态编联产生的目的是通过基类类型的指针指向不同对象时自动调用相应的、和基类同名的函数使用同一种调用形式既能调用派生类又能调用基类的同名函数。虚函数需要在基类中加上 virtual 修饰符修饰因为 virtual 会被隐式继承所以子类中相同函数都是虚函数。当一个成员函数被声明为虚函数之后其派生类中同名函数自动成为虚函数在派生类中重新定义此函数时要求函数名、返回值类型、参数个数和类型全部与基类函数相同。 纯虚函数只是相当于一个接口名但含有纯虚函数的类不能够实例化。