基类和派生类非虚函数和成员变量的同名
2015-04-09 21:23
459 查看
对于子类和父类如果拥有同名的data member 或者non virtual 成员函数,会如何处理?如果data member是static类型的又有何不同?(实际上体现了对继承的深刻理解)
对于这样的同名non virtual 函数或者 成员,实际上由指针或者对象的类型决定了访问的具体是哪个?如果使用子类类型的对象或指针,则只能看到子类里的哪个函数或者成员,对于父类里的函数则会产生遮蔽(隐藏)现象(任何时候子类中重新定义了基类中的函数,基类中所有同名的重载函数都自动隐藏了),如果想访问父类成员,必须加上父类的名称限定,【实现模型】也就是说实际上编译器在实现中自动地对这种重名现象进行了处理,给父类对象加上了一个限定词合成了一个新的名称。但是如果没有发生这种重名现象,子类类型的对象或指针,依然可以正常访问从父类继承下来的那些成员。 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; }
相关文章推荐
- C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)
- 内存对齐(成员涉及基本变量和位域,不涉及虚函数、虚基类)
- 关于如何在派生类的虚函数中调用被覆盖掉的同名基类的虚函数
- 假设派生类继承自两个基类,而两个基类中有同名虚函数,问虚表
- 关于如何在派生类的虚函数中调用被覆盖掉的同名基类的虚函数
- 派生类的构造函数中,可以将基类作为成员变量进行初始化
- c++ 基类已经存在virtual修饰的同名成员函数,派生类加不加无所谓,都是virtual的
- 7.26派生类成员函数与基类成员函数同名
- 基类、派生类、派生类成员变量的构造和析构顺序
- c++中基类和子类的成员变量同名,成员函数也同名
- 派生类和基类中的成员变量名相同(转)
- 基类、派生类、派生类成员变量的构造和析构顺序
- [疑问]C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
- 基类和派生类之间的同名函数处理方式
- 第十二周阅读程序4:虚基类-同名数据成员
- C++第十二周【任务1】理解基类中成员的访问限定符和派生类的继承方式
- 派生类可以访问基类的private成员吗
- 基类和派生类的成员访问
- PetShop 4.0知识点:base 关键字用于从派生类中访问基类的成员
- C++第十三周任务-项目一(理解基类中成员的访问限定符和派生类的继承方式)