您的位置:首页 > 其它

基类和派生类非虚函数和成员变量的同名

2015-04-09 21:23 459 查看
对于子类和父类如果拥有同名的data member 或者non virtual 成员函数,会如何处理?如果data member是static类型的又有何不同?(实际上体现了对继承的深刻理解)

对于这样的同名non virtual 函数或者 成员,实际上由指针或者对象的类型决定了访问的具体是哪个?如果使用子类类型的对象或指针,则只能看到子类里的哪个函数或者成员,对于父类里的函数则会产生遮蔽(隐藏)现象(任何时候子类中重新定义了基类中的函数,基类中所有同名的重载函数都自动隐藏了),如果想访问父类成员,必须加上父类的名称限定,【实现模型】也就是说实际上编译器在实现中自动地对这种重名现象进行了处理,给父类对象加上了一个限定词合成了一个新的名称。但是如果没有发生这种重名现象,子类类型的对象或指针,依然可以正常访问从父类继承下来的那些成员。 static
数据成员也同理。
如果使用基类类型的对象或指针(即使用派生类对象地址来初始化),则永远只能看到基类里的函数和成员,不能显示访问子类的对象。

class Base
{

public:
Base():a(1){}
virtual void func() {cout<<"Base"<<endl;}

int f() const{
cout<<"Base::f()\n";
return 1;
}

int f(string str) const {cout<<str<<endl; return 1;}
int a;
static int  s;
};

class Derive : public Base

{

public:
Derive():a(2){}
void func() {cout<<"Derive"<<endl;}
/*
int f() const{
cout<<"Derive::f()\n";
return 1;
}
*/

void f() const{
cout<<"void f() \n";
}
// 上面的两个f()不能同时存在一个类中,因为无法重载仅按返回类型区分的non-virtual函数;可放在其他从Base派生的类中

int a;
static int s;
};

int Base::s = 0;  //static变量初始化
int Derive::s = 1;

int main()
{
Derive d;
Derive *pa = &d;
//一般成员变量
cout<<pa->a<<endl;  //pa为Derive类型,由于基类和派生类有同名的a, 对基类中的a会隐藏,实际上是给父类的对象a加上了一个限定词。默认访问的是Derive类中的a = 2
cout<<pa->Base::a<<endl;  // 若想访问基类的a,必须显示指定

//static member
cout<<pa->s<<endl;  ///pa为Derive类型,对基类中的静态成员s隐藏,默认访问Derive的s
cout<<pa->Base::s<<endl;  //显示访问Base的s

//member function
pa->f(); // pa为Derive类型,Derive对f进行了重新定义,隐藏了基类中的所有f的重载版本;默认访问Derive的f
pa->Base::f();  //显示访问Base的f

// !!! pa->f("abc");  //派生类对non-virtual 函数进行改写(重新定义或参数列表,返回值改变)时,派生类中的函数会隐藏基类中的所有重载版本!!因此,不能访问基类的f(string){};
pa->Base::f("abc");   //只能通过显示访问被隐藏的Base::f(string)

Base *pb = &d;
cout<<pb->a<<endl;  //pb为Base类型,默认且只能访问Base类中的a = 1;
cout<<pb->s<<endl;
//!!!  cout<<pb->Derive::a<<endl;  // 出错,提示限定名不是Base或其基类的成员。因为父类指针pb是无法访问子类里的public成员变量或者函数的
//可以使用强制转换static_cast<Derive*>(pb)实现;
cout<<static_cast<Derive*>(pb)->s<<endl;  //pb强制转换为Derive型后,和pa一样,默认访问的是Derive的a = 2;
cout<<pb->a<<endl;  //此时上面的转换失效,pb仍然还是Base* 类型。

cout<<pb->s<<endl;
pb->f(); //
pb->f("123");
//!!! pb->Derive::f();  //显示访问Derive的f,错误,pb为Base*,不能访问Derived的成员

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐