关于继承,函数的继承
2013-06-17 14:19
134 查看
1. 子类拥有了父类的public财产(私有成员其实也有,但是访问不了),通过子类调用函数时,编译器先在子类中找相应的函数,找不到的话再去父类找。
如此一来,如果父类和子类定义了一样的函数(包括参数列表),子类的函数会覆盖父类函数。
如果,父类定义了子类的同名函数,但是参数列表不同,子类的也会被覆盖隐藏,如
果想通过子类调用父类的函数,需要显示的说明,比如 b.A::XXXX(p1, p2)
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
B *pb = &b;
pa->print();
pb->print();
getchar();
return 0;
}
所以这段代码输出 This is A 和 This is B
2. 下面的代码
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
A *pb = &b; // 这行是关键
pa->print();
pb->print();
getchar();
return 0;
}
居然,输出是 两个 “This is A”。
3. 所以虚函数便应运而生,很好解决了同名函数继承的多态问题。
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
virtual void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
A *pb = &b;
pa->print();
pb->print();
getchar();
return 0;
}
输出是 This is A 和 This is B
PS。虚函数的多态,严格按照函数名+参数名。也就是说子类和父类的函数名和参数都得完全一致。
而函数隐藏却不需要这么严格,只要函数名一样的就隐藏函数。
覆盖
如果派生类覆盖了基类中的成员函数或成员变量,则当派生类的对象调用该函数或
变量时是调用的派生类中的版本,当用基类对象调用该函数或变量时是调用的基类中的版本。
隐藏
看下边这个例子,B继承A 为什么main函数执行fun(x),fun(x,y)时编译通不过
class A
{
public:
void f(int i,int j){
i=i+j;
cout<<i<<endl;
}
void f(int i){
cout<<i<<endl;
}
};
class B:public A//private A
{
public:
//using A::fun;
/*void f(){
a=10;
cout<<a<<endl;
}*/
private:
int a;
};
int main(){
B m;
m.f(5,1);
//m.A::f(5,1);
}
其实很简单
隐藏基类成员函数的情况:如果在派生类中定义了一个与基类同名的函数,不管这个函数的参数列表是不是与基类
中的函数相同,则这个同名的函数就会把基类中的所有这个同名的函数的所有重载版本都隐藏了,这时并不是在派
生类中重载基类的同名成员函数,而是隐藏,比如类A中有函数f(int i,intj)和f(int i)两个版本,当在从A派生出的类
B中定义了基类的f()函数版本时,这时基类中的fun(int i)和f(int i,int j)就被隐藏了,也就是说由类B创建的对象比如
为m,不能直接访问类A中的f(int i)版本,即使用语句m.f(2)时会发生错误。
怎样使用派生类的对象访问基类中被派生类覆盖或隐藏了的函数或变量:
方法 1 使用作用域运算符::,在使用对象调用基类中的函数或变量时使用作用域运算符即语句 m.A::f(2),这
时就能访问基类中的函数或变量版本。注意,访问基类中被派生类覆盖了的成员变量只能用这种方法
方法 2 使用 using:该方法只适用于被隐藏或覆盖的基类函数,在派生类的类定义中使用语句 using 把基类的
名字包含进来,比如using A::f;就是将基类中的函数f()的所有重载版本包含进来,重载版本被包含到子类之
后,这些重载的函数版本就相当于是子类的一部分,这时就可以用派生类的对象直接调用被派生类隐藏了的
基类版本,比如 m.f(2),但是使用这种语句还是没法调用基类在派生类中被覆盖了的基类的函数,比如 m.f()
调用的是派生类中定义的函数f,要调用被覆盖的基类中的版本要使用语句m.A::f()才行。
在派生类的函数中调用基类中的成员变量和函数的方法:就是在函数中使用的被派生类覆盖的基类成员变量或函数
前用作域解析符加上基类的类名,即a::f()就是在派生类的函数中调用基类中被派生类覆盖了的函数f()的方法。
派生类以私有方式被继承时改变基类中的公有成员为公有的方法:
使用::作用域运算符,不提倡用这种方法,在派生类的 public 后面用作用域运算符把基类的 公有成员包函进
来,这样基类的成员就会成为派生类中的公有成员了,注意如果是函数的 话后面不能加括号 ,如A::f;如果
f是函数的话不能有括号
使用using语句,现在一般用这种方法,也是在派生类的public使用using把基类成员包函进来,如using A::f。
如此一来,如果父类和子类定义了一样的函数(包括参数列表),子类的函数会覆盖父类函数。
如果,父类定义了子类的同名函数,但是参数列表不同,子类的也会被覆盖隐藏,如
果想通过子类调用父类的函数,需要显示的说明,比如 b.A::XXXX(p1, p2)
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
B *pb = &b;
pa->print();
pb->print();
getchar();
return 0;
}
所以这段代码输出 This is A 和 This is B
2. 下面的代码
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
A *pb = &b; // 这行是关键
pa->print();
pb->print();
getchar();
return 0;
}
居然,输出是 两个 “This is A”。
3. 所以虚函数便应运而生,很好解决了同名函数继承的多态问题。
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() {}
virtual void print() { cout << "This is A\n"; }
};
class B: public A
{
public:
B() {}
~B() {}
void print() { cout << "This is B\n"; }
};
int main()
{
A a;
B b;
A *pa = &a;
A *pb = &b;
pa->print();
pb->print();
getchar();
return 0;
}
输出是 This is A 和 This is B
PS。虚函数的多态,严格按照函数名+参数名。也就是说子类和父类的函数名和参数都得完全一致。
而函数隐藏却不需要这么严格,只要函数名一样的就隐藏函数。
覆盖
如果派生类覆盖了基类中的成员函数或成员变量,则当派生类的对象调用该函数或
变量时是调用的派生类中的版本,当用基类对象调用该函数或变量时是调用的基类中的版本。
隐藏
看下边这个例子,B继承A 为什么main函数执行fun(x),fun(x,y)时编译通不过
class A
{
public:
void f(int i,int j){
i=i+j;
cout<<i<<endl;
}
void f(int i){
cout<<i<<endl;
}
};
class B:public A//private A
{
public:
//using A::fun;
/*void f(){
a=10;
cout<<a<<endl;
}*/
private:
int a;
};
int main(){
B m;
m.f(5,1);
//m.A::f(5,1);
}
其实很简单
隐藏基类成员函数的情况:如果在派生类中定义了一个与基类同名的函数,不管这个函数的参数列表是不是与基类
中的函数相同,则这个同名的函数就会把基类中的所有这个同名的函数的所有重载版本都隐藏了,这时并不是在派
生类中重载基类的同名成员函数,而是隐藏,比如类A中有函数f(int i,intj)和f(int i)两个版本,当在从A派生出的类
B中定义了基类的f()函数版本时,这时基类中的fun(int i)和f(int i,int j)就被隐藏了,也就是说由类B创建的对象比如
为m,不能直接访问类A中的f(int i)版本,即使用语句m.f(2)时会发生错误。
怎样使用派生类的对象访问基类中被派生类覆盖或隐藏了的函数或变量:
方法 1 使用作用域运算符::,在使用对象调用基类中的函数或变量时使用作用域运算符即语句 m.A::f(2),这
时就能访问基类中的函数或变量版本。注意,访问基类中被派生类覆盖了的成员变量只能用这种方法
方法 2 使用 using:该方法只适用于被隐藏或覆盖的基类函数,在派生类的类定义中使用语句 using 把基类的
名字包含进来,比如using A::f;就是将基类中的函数f()的所有重载版本包含进来,重载版本被包含到子类之
后,这些重载的函数版本就相当于是子类的一部分,这时就可以用派生类的对象直接调用被派生类隐藏了的
基类版本,比如 m.f(2),但是使用这种语句还是没法调用基类在派生类中被覆盖了的基类的函数,比如 m.f()
调用的是派生类中定义的函数f,要调用被覆盖的基类中的版本要使用语句m.A::f()才行。
在派生类的函数中调用基类中的成员变量和函数的方法:就是在函数中使用的被派生类覆盖的基类成员变量或函数
前用作域解析符加上基类的类名,即a::f()就是在派生类的函数中调用基类中被派生类覆盖了的函数f()的方法。
派生类以私有方式被继承时改变基类中的公有成员为公有的方法:
使用::作用域运算符,不提倡用这种方法,在派生类的 public 后面用作用域运算符把基类的 公有成员包函进
来,这样基类的成员就会成为派生类中的公有成员了,注意如果是函数的 话后面不能加括号 ,如A::f;如果
f是函数的话不能有括号
使用using语句,现在一般用这种方法,也是在派生类的public使用using把基类成员包函进来,如using A::f。
相关文章推荐
- 关于继承的构造,函数的调用
- 关于C#间接继承的一些思考:如何修改继承函数的返回值类型
- 关于Python中的类普通继承与super函数继承
- 关于继承,函数的继承
- 关于C++多重继承的时候虚函数覆盖的问题
- 关于继承中的 纯虚函数、虚函数和非虚函数的总结
- 关于virtual、非virtual继承函数的调用
- 一篇关于虚继承和虚函数介绍的很好的文章
- 关于多重继承中覆盖虚基类的函数问题--《C++程序设计语言》
- 关于c++多重继承下的函数调用注意的问题
- 关于execl()函数继承控制终端的实验
- Effective C++: 关于继承中的函数的访问级别的修改.
- COM接口继承IUnkonwn接口,关于IUnkonwn里面函数实现中用到引用计数的总结
- 关于C++虚继承、虚函数继承的几个例子
- 关于Python中的类普通继承与super函数继承
- 关于函数的多态,与继承,以及相关的名词
- 关于javascript中变量是如何存储调用、以及函数的继承实现
- 软件设计本质论(Essential Design) —白话面向对象 (转注:关于c语言实现封装继承多态的一堆博文)
- 关于C++中_finite()函数的说明 [转]
- 关于函数传参问题