public继承后,父类与子类访问隐藏
2012-08-17 10:54
183 查看
《Effective C++》的第六章节继承与面向对象设计花了大部分的篇幅在介绍继承遮掩(Hiding Inherited Name),那我也效仿下大师,做个小的总结。
public继承的目的是要建立父子类的is-a关系,也就是说用到父类的地方,在子类一定能用。现实的代码编写中,我们主要也是用public继承,所以每个人都有自己一套继承的写法和调用,直到看到Effecitve C++时,才会发现还有很多其它的用法,在这里我并不鼓励大家尝试各种写法,毕竟代码要稳定,我只是想把一些可能的形式表现出来,供大家参考。
class Base
{
public:
virtual void fn() = 0;
virtual void fn(int i){printf("\n Base: fn(int)\n");};
virtual void fn2() {printf("\n Base: void fn2(int)\n");}
void fn3() {printf("\n Base: fn3()\n");}
void fn4(){printf("\n Base: fn4()\n");}
};
class ClassA : public Base
{
public:
ClassA(int n, int d);
// using Base::fn2;
virtual void fn(){printf("\n ClassA: fn()\n");};
virtual void fn(int i){printf("\n ClassA: fn(INT)\n");};
virtual void fn2(int i) {printf("\n ClassA: fn2(INT)\n"); }
void fn3() {printf("\n ClassA: fn3()\n");}
void fn4(int i){printf("\n ClassA: fn4()\n");}
};
int main()
{
Base* pBase1 = new ClassA(10, 20);
pBase1->fn(); //OK,ClassA: fn()
pBase1->fn(11); //OK,ClassA: fn(INT)
pBase1->fn2(); //OK,Base: void fn2(int)
pBase1->fn2(2); //NO, 不能访问
pBase1->fn3(); //OK,Base: fn3()
pBase1->fn4(); //OK,Base: fn4()
pBase1->fn4(2); //NO,不能访问
printf("\n============================================\n");
ClassA* pDerived = new ClassA(10, 20);
pDerived->fn(); //OK,ClassA: fn()
pDerived->fn(1); //OK,ClassA: fn(INT)
pDerived->fn2(); //NO,不能访问
pDerived->fn2(2); //OK,ClassA: fn2(INT)
pDerived->fn3(); //OK,ClassA: fn3()
pDerived->fn4(); //NO,不能访问
pDerived->fn4(2); //NO,ClassA: fn4(INT)
printf("\n============================================\n");
return 0;
}
子类父类同名virtual函数(参数相同), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数相同), 用父类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数不同), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数不同), 用父类的指针,引用,对象访问时,父类会覆盖子类方法(只能访问父类方法)。
子类父类同名virtual函数(函数类型不同const/non-const), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(函数类型不同const/non-const), 用父类的指针,引用,对象访问时,父类会覆盖子类方法(只能访问父类方法)。
结论:参数和函数类型是c++编译器判断要不要多态的关键因素。注: 返回类型不同时,编译器会报错,virtual不能和static连用。静态成员函数,没有隐藏的this指针,virtual函数一定要通过对象来调用,既要this指针。
改进::如果子类指针想访问到父类,可以在子类里加入:using 父类名::函数名;如pDerived->fn2(); 访问父类方法,在ClassA里面加入using Base::fn2,就可以访问了。如果父类指针想访问到子类,就需要指针转换了。
子类父类同名non-virtual函数(无论参数/返回/函数类型(const或static)),用子类的指针,引用,对象访问,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名non-virtual函数(无论参数/返回/函数类型(const或static)),用父类的指针,引用,对象访问,父类会覆盖子类方法(只能访问父类方法)。
结论: non-virtual函数,既没有任何多态效果,如果父类要访问子类,只用指针转换。
所谓大道至简,想必大家看着这个都烦,我也是。想了想应该这样表达最简单:
子类public继承父类的函数,唯有满足(参数,返回值,函数类型相同&父类是virtual)函数,父类的指针,引用(也指针实现的)能够多态的访问子类,否则父类指针只能访问父类的方法。
子类public继承父类的函数,子类的方法名会遮掩父类的相同名的方法。子类要想访问父类的方法,使用using 父类名::函数名。
具体的原因我觉得可能还是得找时间拜读下候杰译的《C++对象模型》,看看到底这个东西是怎么设计的。
public继承的目的是要建立父子类的is-a关系,也就是说用到父类的地方,在子类一定能用。现实的代码编写中,我们主要也是用public继承,所以每个人都有自己一套继承的写法和调用,直到看到Effecitve C++时,才会发现还有很多其它的用法,在这里我并不鼓励大家尝试各种写法,毕竟代码要稳定,我只是想把一些可能的形式表现出来,供大家参考。
class Base
{
public:
virtual void fn() = 0;
virtual void fn(int i){printf("\n Base: fn(int)\n");};
virtual void fn2() {printf("\n Base: void fn2(int)\n");}
void fn3() {printf("\n Base: fn3()\n");}
void fn4(){printf("\n Base: fn4()\n");}
};
class ClassA : public Base
{
public:
ClassA(int n, int d);
// using Base::fn2;
virtual void fn(){printf("\n ClassA: fn()\n");};
virtual void fn(int i){printf("\n ClassA: fn(INT)\n");};
virtual void fn2(int i) {printf("\n ClassA: fn2(INT)\n"); }
void fn3() {printf("\n ClassA: fn3()\n");}
void fn4(int i){printf("\n ClassA: fn4()\n");}
};
int main()
{
Base* pBase1 = new ClassA(10, 20);
pBase1->fn(); //OK,ClassA: fn()
pBase1->fn(11); //OK,ClassA: fn(INT)
pBase1->fn2(); //OK,Base: void fn2(int)
pBase1->fn2(2); //NO, 不能访问
pBase1->fn3(); //OK,Base: fn3()
pBase1->fn4(); //OK,Base: fn4()
pBase1->fn4(2); //NO,不能访问
printf("\n============================================\n");
ClassA* pDerived = new ClassA(10, 20);
pDerived->fn(); //OK,ClassA: fn()
pDerived->fn(1); //OK,ClassA: fn(INT)
pDerived->fn2(); //NO,不能访问
pDerived->fn2(2); //OK,ClassA: fn2(INT)
pDerived->fn3(); //OK,ClassA: fn3()
pDerived->fn4(); //NO,不能访问
pDerived->fn4(2); //NO,ClassA: fn4(INT)
printf("\n============================================\n");
return 0;
}
子类父类同名virtual函数(参数相同), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数相同), 用父类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数不同), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(参数不同), 用父类的指针,引用,对象访问时,父类会覆盖子类方法(只能访问父类方法)。
子类父类同名virtual函数(函数类型不同const/non-const), 用子类的指针,引用,对象访问时,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名virtual函数(函数类型不同const/non-const), 用父类的指针,引用,对象访问时,父类会覆盖子类方法(只能访问父类方法)。
结论:参数和函数类型是c++编译器判断要不要多态的关键因素。注: 返回类型不同时,编译器会报错,virtual不能和static连用。静态成员函数,没有隐藏的this指针,virtual函数一定要通过对象来调用,既要this指针。
改进::如果子类指针想访问到父类,可以在子类里加入:using 父类名::函数名;如pDerived->fn2(); 访问父类方法,在ClassA里面加入using Base::fn2,就可以访问了。如果父类指针想访问到子类,就需要指针转换了。
子类父类同名non-virtual函数(无论参数/返回/函数类型(const或static)),用子类的指针,引用,对象访问,子类会覆盖父类方法(只能访问子类方法)。
子类父类同名non-virtual函数(无论参数/返回/函数类型(const或static)),用父类的指针,引用,对象访问,父类会覆盖子类方法(只能访问父类方法)。
结论: non-virtual函数,既没有任何多态效果,如果父类要访问子类,只用指针转换。
所谓大道至简,想必大家看着这个都烦,我也是。想了想应该这样表达最简单:
子类public继承父类的函数,唯有满足(参数,返回值,函数类型相同&父类是virtual)函数,父类的指针,引用(也指针实现的)能够多态的访问子类,否则父类指针只能访问父类的方法。
子类public继承父类的函数,子类的方法名会遮掩父类的相同名的方法。子类要想访问父类的方法,使用using 父类名::函数名。
具体的原因我觉得可能还是得找时间拜读下候杰译的《C++对象模型》,看看到底这个东西是怎么设计的。
相关文章推荐
- public继承后,父类与子类访问隐藏 熟练c/c++(三)
- Java中子类的基本继承方法,子类通过继承父类public方法,访问父类private成员
- 子类会继承父类的私有方法和私有属性,只是不能直接访问
- C++ 类的继承,子类以及之类的对象 对父类成员函数的访问权限
- 父类的正常成员函数子类可以使用,并不是继承下来 的,子类是怎么调用父类的函数 : 可能是利用了一种叫函数名联编的方法.没有隐藏的情况下用函数名字来决定调用的函数.
- OC中继承子类对象调用方法机制 子类对象访问父类中的实例变量
- 子类继承父类后重载protected方法提升访问权限为public
- OC中继承子类对象调用方法机制 子类对象访问父类中的实例变量
- 子类继承父类放法访问权限的问题
- 子类继承父类 构造函数访问问题
- OC 继承子类对象调用方法机制 子类对象访问父类中的实例变量
- c++模板类在继承中子类无法访问父类的成员
- java 父类访问子类对象的实例变量 继承过程中的执行顺序
- java 类继承两个父类,同名变量 public 比protected具有优先访问权限
- C++中指向子类的父类指针访问父、子类成员时的权限和函数隐藏规则
- 在继承中,父类的私有也会被继承,但是子类不可以直接访问,但是可以间接的访问
- 公有继承,私有继承,保护继承下访问父类和子类的区别
- 子类继承父类的私有属性和方法但是不能访问父类私有属性和方法
- 父类中的private方法会被子类继承吗????可以访问吗????
- java之中的四种访问权限和子类如何继承父类特性