首页 > 代码库 > C++语言笔记系列之十四——继承后的访问权限

C++语言笔记系列之十四——继承后的访问权限

1.析构函数不继承;派生类对象在析构时,基类析构函数的调用顺序与构造函数相反。
注:派生类对象建立时要调用基类构造函数,派生类对象删除时要调用基类析构,顺序与构造函数严格相反。
2.例子
example 1

#include <iostream.h>
#include <math.h>

class Point
{
public:
    Point(double a, double b, doule c)
    {
        x = a;
        y = b;
        z = c;
    }
    double Getx() {return x;}
    double Gety() {return y;}
    double Getz() {return z;}
private:
    double x, y;
    double z;
};
class Line:public Point
{
public:
    Line(double a, double b, double c, double d):Point(a, b, c)
    {k = d;}
    void show()
    {
        cout<<Getx()<<endl;
        cout<<Gety()<<endl;
        cout<<Getz()<<endl;
    }
private:
    double k;
};

int main()
{
    line obj(1.2, 3.4, 5.6, 7.8);
    obj.show();
}
问题:class Line:public Point中的public可否换成protected?
答:可以,因为公有继承和保护继承,基类中的公有或者受保护成员在派生类中都可以被访问。

example 2

class Point
{
public:
    Point(int i = 0, int j = 0) {x = i; y = j;}
    void move(int xoff, int yoff) {x += xoff; yf += yoff;}
    int Getx() {return x;}
    int Gety() {return y;}
private:
    int x, y;
};
class Rectangle:private Point
{
public:
    Rectangle(int x, int y, int w, int h):Point(x, y)
    {
        W = w;
        H = h;
    }
    void move(int xoff, int yoff)
    {
        Point::move(int xoff, int yoff);    
    }
    int Getx() {return Point::Getx();}
    int Gety() {return Point::Gety();}
    int GetW() {return W;}
    int GetH() {return H;}
private:
    int W, H;
};

int main()
{
    Rectangle Rect(1, 2, 3, 4);
    Rect.move(5, 6);
    cout<<"The data of Rect(x, y, W, H):("<<Rect.Getx()<<", "<<Rect.Gety()<<", "<<Rect.GetW()<<", "<<Rect.GetH()<<endl;
}
注:无论该题目的继承方式为public还是protected,调用的Rect.move都是派生类中的move函数(优先派生类)。调用顺序是:
基类-->基类;派生类-->派生类(若无)-->基类。
3.继承的支配规则
基类无法访问派生类的成员。派生类对象或成员也可以引用基类同名成员,这时候需要加上基类的类名作用域。
派生类对象调用:派生类对象.基类名::成员函数()
派生类成员调用:基类名::成员函数
4.例子
example 1

#include <iostream.h>
class Base
{
public:
    void f1() {}
    void f3() {}
};
class devived:public Base
{
public:
    void f1() {}
    void f2() {}
};

int main()
{
    Base B1, *pb1;
    devived d1, *pd1;
    pb1 = &B1;
    pd1 = &d1;
    B1.f1(); //访问基类的f1()
    pb1->f1(); //访问基类中的f1()
    d1.f1(); //访问派生类中的f1()
    pd1.f1(); //访问派生类中的f1()
    pb1->f2(); //访问错误,没有这个成员
    d1.Base::f1(); //访问基类的f1()
    pd1->Base::f1(); //访问基类的f1()
    d1.f3(); //访问基类中的f3()
    pd1->f3(); //访问基类中的f3()
}
注:派生类对象在引用基类的同名成员时,必须加类的作用域(因为同名成员会优先派生类成员)。
在派生类f2()中访问派生类的f1():
f2() {f1()} //直接访问即可
在派生类f2()中访问基类的f1():
f2() {Base::f1()}

修改:pb1 = &d1; pb1->f1(); //访问的是基类中的f1(),因为虽然给基类的指针赋值了派生类的值,但是所指部分仍然只有派生类中继承来的基类的部分。

example 2

#include <iostream.h>
class X
{
public:
    int a;
};
class Y1:public X
{};
class Y2:protected X
{};
class Y3:private X
{
private:
    void f(Y1 *py1, Y2 *py2, Y3 *py3);
};
class Z:private Y2
{
private:
    void f(Y1 *py1, Y2 *py2, Y3 *py3);
};

void f(Y1 *py1, Y2 *py2, Y3 *py3)
{
    py1->a = 7; //Y
    py2->a = 7; //N:类外不可以访问类内的受保护成员
    py3->a = 7; //N:类外不可以访问类内的私有成员(私有继承过来的,类内也不可直接访问)
}

void Y3::f(Y1 *py1, Y2 *py2, Y3 *py3)
{
    py1->a = 7; //Y
    py2->a = 7; //N
    py3->a = 7; //Y,基类中的公有a被继承为私有,类内部可以访问
}

void Z::f(Y1 *py1, Y2 *py2, Y3 *py3)
{
    py1->a = 7; //Y
    py2->a = 7; //N,该指针指向的是Y2,并非Z
    py3->a = 7; //N
}
注:友元函数与类无是一个普通函数,所以友元函数不会继承。