C++继承类和基类之间成员函数和虚函数调用机制
2012-11-22 22:12
459 查看
今天去参加百度的面试,遇到一个关于虚函数的机制的问题,我一直认为就是为了让基类指针或引用(指向继承类)能够看到基类的虚函数(当基类的虚函数没有被继承类重写),但是继承类又怎么看到基类的普通成员函数呢?我开始想,好想不可以调用基类的成员函数,因为基类的成员函数不是虚函数,在虚表找不到它,好吧,明天被鄙视了。回到家好好的研究了一下虚函数和成员函数,看看基类的成员函数和虚函数在派生类指针或引用是否可见,还有基类的成员函数和虚函数在基类指针或引用(指向继承类)是否可见,以及派生类的成员函数和虚函数在基类指针或引用(指向继承类)是否可见?
下面是例子:
#include <iostream>
using namespace std;
class A
{
public:
A(int i) { n=i; }
A(){ n=1;}
virtual void f(){ std::cout<<"A.f() is used"<<endl;}
void g(){ std::cout<<"A.g() is used"<<endl;}
void k(){ std::cout<<"A.k() is used"<<endl;}
private:
int n;
};
class B:public A
{
public:
B(int i) { n=i; }
B(){ n=1;}
void f(){ std::cout<<"B.f() is used"<<endl;}
void g(){ std::cout<<"B.g() is used"<<endl;}
void h(){ std::cout<<"B.h() is used"<<endl;}
virtual void j(){ std::cout<<"B.h() is used"<<endl;}
private:
int n;
};
class C
{
public:
C(int i) { n=i; }
C(){ n=1;}
void w(){ std::cout<<"C.w() is used"<<endl;}
private:
int n;
};
int main()
{
B b;
b.k(); //b显然能看到A中的k()
A *a;
a=&b;
a->f(); //a看到的是B的f()
a->A::f(); //a看到的是A的f()
a->g(); //a看到的是A的g()
a->h(); //a看不到B的h()
a->j(); //a看不到B的虚拟函数j()
cout<<a->C::n<<endl; //看不到
a->C::w(); //看不到
while(1)
{
}
}
一个类的对象中是没有关于普通成员函数的指针的slot,只有成员变量还有虚表指针,类的成员函数的代码定义在PE文件的代码区,所以从程序加载时,就已经分配好了内存用于存放这些代码;代码运行时所需要的内存,比如栈、堆等等,则是代码运行时才分配的;对于某个类的所有对象来说,类成员函数只在内存中有一份拷贝,所有的对象都共享同一份成员函数的代码。同一个类的不同的对象之间的差异仅仅是通过成员变量来体现的。c++实现成员函数的时候实际上用到了一个技巧——this指针。this指针是当前调用成员函数的对象首地址,我们知道通过这个地址可以访问到对应对象的成员变量。那么成员函数如何区分this究竟指向哪个对象呢?技巧就在于,c++背后把成员函数当做普通函数一样调用,除了传入实际的参数外,还把所属对象的指针作为参数this传入,函数内部通过显示的或者隐含的方式访问对象成员。当然,这只是背后的事情,外面用起来就和你见到的一样,简单直观。
http://bbs.csdn.net/topics/80228792
http://blog.csdn.net/haoel/article/details/1948051
下面是例子:
#include <iostream>
using namespace std;
class A
{
public:
A(int i) { n=i; }
A(){ n=1;}
virtual void f(){ std::cout<<"A.f() is used"<<endl;}
void g(){ std::cout<<"A.g() is used"<<endl;}
void k(){ std::cout<<"A.k() is used"<<endl;}
private:
int n;
};
class B:public A
{
public:
B(int i) { n=i; }
B(){ n=1;}
void f(){ std::cout<<"B.f() is used"<<endl;}
void g(){ std::cout<<"B.g() is used"<<endl;}
void h(){ std::cout<<"B.h() is used"<<endl;}
virtual void j(){ std::cout<<"B.h() is used"<<endl;}
private:
int n;
};
class C
{
public:
C(int i) { n=i; }
C(){ n=1;}
void w(){ std::cout<<"C.w() is used"<<endl;}
private:
int n;
};
int main()
{
B b;
b.k(); //b显然能看到A中的k()
A *a;
a=&b;
a->f(); //a看到的是B的f()
a->A::f(); //a看到的是A的f()
a->g(); //a看到的是A的g()
a->h(); //a看不到B的h()
a->j(); //a看不到B的虚拟函数j()
cout<<a->C::n<<endl; //看不到
a->C::w(); //看不到
while(1)
{
}
}
一个类的对象中是没有关于普通成员函数的指针的slot,只有成员变量还有虚表指针,类的成员函数的代码定义在PE文件的代码区,所以从程序加载时,就已经分配好了内存用于存放这些代码;代码运行时所需要的内存,比如栈、堆等等,则是代码运行时才分配的;对于某个类的所有对象来说,类成员函数只在内存中有一份拷贝,所有的对象都共享同一份成员函数的代码。同一个类的不同的对象之间的差异仅仅是通过成员变量来体现的。c++实现成员函数的时候实际上用到了一个技巧——this指针。this指针是当前调用成员函数的对象首地址,我们知道通过这个地址可以访问到对应对象的成员变量。那么成员函数如何区分this究竟指向哪个对象呢?技巧就在于,c++背后把成员函数当做普通函数一样调用,除了传入实际的参数外,还把所属对象的指针作为参数this传入,函数内部通过显示的或者隐含的方式访问对象成员。当然,这只是背后的事情,外面用起来就和你见到的一样,简单直观。
http://bbs.csdn.net/topics/80228792
http://blog.csdn.net/haoel/article/details/1948051
相关文章推荐
- C++继承类和基类之间成员函数和虚函数调用机制
- C++继承类和基类之间成员函数和虚函数调用机制
- 关于C++虚函数与普通函数的编译与调用机制
- [疑问]C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
- 定义一个哺乳动物Mammal类,再由此派生出狗Dog类,二者都定义 Speak()成员函数,基类中定义为虚函数,定义一个Dog类的对象,调用Speak函数,观察运行结果
- C++如何在派生类成员函数内调用基类的成员函数(包括构造函数)
- C++中通过派生类调用第二基类的普通成员函数时this指针的调整
- C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
- C++调用动态库中的虚基类成员函数时总是进错函数
- C++中继承机制下基类public/private/protected成员的访问方式
- 在一个类里面 成员函数之间的互相调用
- C++中的成员函数调用原理及this指针的传递方式
- C++之静态成员函数为什么不能为虚函数
- 使用类成员函数指针调用C++成员函数的一种方式
- C++调用空指针对象的成员函数——静态绑定与动态绑定
- [转]浅析C++中虚函数的调用及对象的内部布局(利用汇编深刻理解C++虚函数底层实现机制)
- 为什么C++静态成员函数不能访问非静态成员变量、不能调用非静态成员函数?(面试常考)
- 转: C++指针直接调用类成员函数探讨
- C++静态成员函数不能调用非静态成员变量(详解)
- c++静态成员函数为什么不能为虚函数?