VS 调试记录

项目中有类似于这样结构的一段代码,特此记录一下调试结果。

class A
{
public:
virtual void func() = 0;
};

class B :public A
{
int b = 1;
public:
virtual void func() override
{
}
};

class C :public A
{
public:
virtual void g()
{
}
private:
int c = 3;
};

class D : public B, public C
{
int d = 4;
public:
virtual void g() override
{
}
virtual void func() override
{
B::func();
}
};

int main(){

B* p = new D; 

可以在调试窗口看到监视信息:




这里因为是菱形继承,所以而且A是抽象类,因为 D 从 C 分支也继承自A, 所以在D内部,必须也给出 func 的定义,否则D 也是抽象类,则不能实例化,发生编译错误。
VS 的监视窗口给出的信息,p 的静态类型是B* , p 自身拥有的而非通过继承而来的成员 b 在最下方。p 指向的对象的动态类型是 D。由于是菱形继承,造成了 A 的子对象实际会出现两次,所以看到中间有个额外的 A 对象。

2、更改为虚继承。

class A
{
public:
virtual void func() = 0;
};

class B : virtual public A
{
int b = 1;
public:
virtual void func() override
{
}
};

class C : virtual public A
{
public:
virtual void g()
{
}
private:
int c = 3;
};

class D : public B, public C
{
int d = 4;
public:
virtual void g() override
{
}
 
};

int main(){
    B* p = new D();
    B* p2 = new B();




改成虚继承, D 中不必再去实现 func 。比较有意思的是可以看到监视窗口中给出,p 和 p2 的结果相同,都是指向的 B 类型对象。这是应为虚继承时,虚基类在每个派生类中都是独立的,上边 B,C,D 对象中包含的 A 对象都是独立的(D中的A 对象并不属于B或者C子对象当中),也就是说,D 中的 func 并不是从 B 中继承而来,而是直接从 A 中继承而来。
换句话说,基类指针或者引用指向派生类对象,实际上指向的是派生类中的基类子对象(派生类对象中包含完整的基类对象)。C++ 中的多态又是通过虚函数表来实现,而 B 的虚函数表是 A 而来的,即 p 指向的子对象中没有与 D 相关的虚函数信息(多态信息)。
。这样导致 D 并没有从 B 继承来与动态类型相关的东西(虚函数),所以看到 p 和 p2 的结果相同。

3、加入在 B 中加入虚函数,

class A
{
public:
virtual void func() = 0;
};

class B : virtual public A
{
public:
virtual void func() override
{
}

virtual void test_func()
{

}
private:
int b = 1;
};

class C : virtual public A
{
public:
virtual void g()
{
}
private:
int c = 3;
};

class D : public B, public C
{
int d = 4;
public:
virtual void g() override
{
}
virtual void func() override
{

}


void sayHello()
{
std::cout << "hello" << "\n";
}
};

int main(){

B* p = new D();
B* p2 = new B();



可以看到这个时候,监视窗口显示的 p 实际的指向的类型已经变成 D (即*p 的动态类型)。

























猜你喜欢

转载自blog.csdn.net/zhouguoqionghai/article/details/78735339
今日推荐