C++ 继承是C++的一个重要概念,以前一直以为自己对继承概念理解了,今天做了一个C++继承的题,才发现自己知识点的盲区,现在先上题,有兴趣的可以做下:
main.cpp
#include <QtCore/QCoreApplication>
#include <QDebug>
class A{
protected:
int m_data;
public:
A(int data = 0)
{
m_data= data;
}
int GetData()
{
return doGetData();
}
virtual int doGetData()
{
return m_data;
}
// int doGetData()
// {
// //qDebug ()<<"virtual data is "<<m_data;
// return m_data;
// }
};
class B:public A{
protected:
int m_data;
public:
B(int data = 1)
{
m_data= data;
}
int GetData ()
{
return m_data;
}
int doGetData ()
{
return m_data;
}
};
class C:public B{
protected:
int m_data;
public:
C(int data = 2)
{
m_data = data;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
C c(10);
qDebug ()<<"c.GetData is "<<c.GetData ();
qDebug ()<<"c.A::GetData is "<<c.A::GetData ();
qDebug ()<<"c.B::GetData is "<<c.B::GetData ();
qDebug ()<<"c.C::GetData is "<<c.C::GetData ();
qDebug ()<<"c.doGetData is "<<c.doGetData ();
qDebug ()<<"c.A::doGetData is "<<c.A::doGetData ();
qDebug ()<<"c.B::doGetData is "<<c.B::doGetData ();
qDebug ()<<"c.C::doGetData is "<<c.C::doGetData ();
return a.exec();
}
写出main 函数里面qDebug中打印的值,各位不妨先思考下再看答案
答案是:
c.GetData is 1
c.A::GetData is 1
c.B::GetData is 1
c.C::GetData is 1
c.doGetData is 1
c.A::doGetData is 0
c.B::doGetData is 1
c.C::doGetData is 1
首先,记住先说下我的理解:
(1)调用的成员函数的时候,会首先去本类里面去寻找成员函数,如果没有找到则会向自己的父类寻找,去调用父类的成员函数。
(2)当调用的成员函数前面有类的描述符的时候,则会去调用类描述符的那个类的成员函数。
(3)当类成员种调用虚函数的时候,会调用派生类中虚函数的最后的实现
上面的话理解不了没关系,我们一个一个来看
– C c(10);
派生类的构造函数,回去自动去调用父类的构造,这个没问题吧,调用顺序C->B->A。
所以现在A::m_data=10;B::m_data=2;C::m_data=10;
qDebug ()<<"c.GetData is "<<c.GetData ();
看下这个调用顺序,c中没有GetData,则会去找父类B的成员函数,父类中有这个函数,直接返回 所以是1.如果父类B中也没这个函数,那么会继续往上找,会找到A的GetData,A中的GetData 调用的是个虚函数,看上面的第一条,A会去找他派生类中的实现,所以最后还是会调用B中的实现,输出1.qDebug ()<<"c.A::GetData is "<<c.A::GetData ();
看第二个,函数前面有类的描述符A,则会去直接调用A的成员函数,然后A成员函数里面有个虚函数,那么他会找到派生类中最后的实现,所以调用的B中的实现,输出1,如果C中也有doGetData,那么则会调用的是C中的doGetData;-
qDebug ()<<"c.B::GetData is "<<c.B::GetData ();
看第三个,函数前面有类的描述符,则会直接去找B的成员函数,返回1 qDebug ()<<"c.C::GetData is "<<c.C::GetData ();
函数前面有类的描述符,会去找C里面的成员函数,因为C里面没有这个成员函数,则会向父类去找,返回B里面的值1.qDebug ()<<"c.doGetData is "<<c.doGetData ();
调用B里面的成员函数qDebug ()<<"c.A::doGetData is "<<c.A::doGetData ();
直接调用A的成员函数qDebug ()<<"c.B::doGetData is "<<c.B::doGetData ();
调用BqDebug ()<<"c.C::doGetData is "<<c.C::doGetData ();
调用B的
这是一个很有意思的问题,在这里整理下,如果看完还是不太理解,可以去掉virtual修饰符,看看是怎么样的输出。