关于继承,函数的继承

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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章