曲径通幽论坛

标题: 继承基本概念与基类的访问控制 [打印本页]

作者: beyes    时间: 2011-8-24 11:13
标题: 继承基本概念与基类的访问控制
继承能够创建层次结构的分类。

可以定义一个通用类,并在该类中定义一些和一组类相关的公共特征,其他类则通过继承的方法以拥有该通用类的特性;进一步来说,继承之后的类又可以在自己的定义中增加各自独有的特征。

被继承的类称为基类;继承之后的类被称为派生类;同时一个派生类也可以作为其他派生类的基类。

继承的通用形式如下所示:
[C++] 纯文本查看 复制代码
class derived-class : access base-class {
// 新类内容
};

其中,access 是可选的,它的选项有 3 个:public, private 或者 protected

下面实例中将创建一个交通工具的基类,在基类中,描述了交通工具的一些共有的特征,然后再创建一个卡车和一个汽车的派生类,卡车和汽车不但拥有交通工具的共用特征,而且还拥有自己的一些独特的特征。

这里,继承时使用上面的 access 为 public 方式,这样表示:基类的所有共有成员也是派生类的公有成员

示例代码:
[C++] 纯文本查看 复制代码

#include <iostream>
using namespace std;

//交通工具基类
class road_vehicle {
        int wheels;     //轮子
        int passengers; //乘客
public:
        void set_wheels(int num) { wheels = num; }
        int get_wheels() { return wheels; }
        void set_pass(int num) { passengers = num; }
        int get_pass() { return passengers; }
};

//定义卡车派生类
class truck : public road_vehicle {
        int cargo;      //货物
public:
        void set_cargo(int size) { cargo = size; }
        int get_cargo() { return cargo; }
        void show();
};

enum type {car, van, wagon};

//定义汽车派生类
class automobile : public road_vehicle {
        enum type car_type;
public:
        void set_type(type t) { car_type = t; }
        enum type get_type() { return car_type; }
        void show();
};

void truck::show()
{
        cout << "wheels: " << get_wheels() << endl;
        cout << "passengers: " << get_pass() << endl;
        cout << "cargo capacity in cubic feet: " << cargo << endl;      //每立方英尺可放多少货物
}

void automobile::show()
{
        cout << "wheels: " << get_wheels() << endl;
        cout << "passengers: " << get_pass() << endl;
        cout << "type: ";
        switch (get_type()) {
                case van:
                        cout << "van\n";
                        break;
                case car:
                        cout << "car\n";
                        break;
                case wagon:
                        cout << "wagon\n";
        }
}

int main()
{
        truck t1, t2;
        automobile c;

        t1.set_wheels(18);
        t1.set_pass(2);
        t1.set_cargo(3200);

        t2.set_wheels(6);
        t2.set_pass(3);
        t2.set_cargo(1200);

        t1.show();
        cout << "\n";
        t2.show();
        cout << "\n";

        c.set_wheels(4);
        c.set_pass(6);
        c.set_type(van);

        c.show();

        return 0;
}

运行输出:
$ ./vehicle
wheels: 18
passengers: 2
cargo capacity in cubic feet: 3200

wheels: 6
passengers: 3
cargo capacity in cubic feet: 1200

wheels: 4
passengers: 6
type: van
当一个类从另一个类继承时,基类的成员也成为了派生类的成员。如上面所说,派生类对基类成员的访问状态是由 public, private 或 protected 这 3 个控制符之一来指定。

如果派生类是 class 类型,那么在忽略访问控制符的情况下,编译器默认使用 private 。
如果派生类是 struct 类型,那么在忽略访问控制符的情况下,编译器默认使用 public 。

public 和 private 的区别
当使用 public 从基类继承时,基类中的所有公有成员都将成为派生类的公有成员。

当使用 private 从基类继承时,基类的所有成员将成为派生类的私有成员。

在所有情况下,基类的私有成员仍将保持为基类的私有成员,不能被派生类访问。

下面程序中,基类 base 的共有成员将成为派生类 derived 的公有成员,他们可以被程序的其他代码访问,但其私有成员不允许派生类直接访问(可通过继承下来的基类中的公有成员函数来访问):
[C++] 纯文本查看 复制代码

#include <iostream>
using namespace std;

class base {
        int i, j;
public:
        void set(int a, int b) { i = a; j = b; }
        void show() { cout << i << " " << j << "\n"; }
};

class derived : public base {
        int k;
public:
        derived(int x) { k = x; }
        void showk() { cout << k << "\n"; }
};

int main()
{
        derived ob(3);

        ob.set(1, 2);   //通过继承基类的成员函数来访问基类的私有成员变量

        ob.i = 10;      //错误,无法直接访问!

        ob.show();

        ob.showk();

        return 0;
}

去掉 ob.i = 10 后,可以通过编译,运行输出:
$ ./base
1 2
3

对比使用 privated 继承的情况(下面程序将不能通过编译):
[C++] 纯文本查看 复制代码

#include <iostream>
using namespace std;

class base {
        int i, j;
public:
        void set(int a, int b) { i = a; j = b; }
        void show() { cout << i << " " << j << "\n"; }
};

//注意,基类的公有成员在派生类中是私有的
class derived : private base {
        int k;
public:
        derived(int x) { k = x; }
        void showk() { cout << k << "\n"; }
};

int main()
{
        derived ob(3);

        ob.set(1, 2);   //错误!使用 private 继承,set()已被认为是派生类中的私有成员


        ob.show();      //错误!同 ob.set(1, 2)

        ob.showk();

        return 0;
}

记住关键一点:
当派生类使用 private 继承基类时,基类的公有成员就将成为派生类的私有成员。这意味着,他们仍然可以被派生类的成员访问,但不能被程序的其他部分访问!

修改上面程序如下:
[C++] 纯文本查看 复制代码

#include <iostream>
using namespace std;

class base {
        int i, j;
public:
        void set(int a, int b) { i = a; j = b; }
        void show() { cout << i << " " << j << "\n"; }
};

//注意,基类的公有成员在派生类中是私有的
class derived : private base {
        int k;
public:
        derived(int x) { k = x; }
        void showk() { cout << k << "\n"; }
        void setd(int x, int y) { set(x, y); }
        void showd() { show(); }
};

int main()
{
        derived ob(3);
        ob.showk();

        ob.setd(10, 9);


        ob.showd();


        return 0;
}

运行输出:
$ ./private
3
10 9
在上面程序中,我们为派生类添加了两个函数 setd() 和 showd(),我们就在这两个函数内访问了从基类中继承下来的函数 set() 和 show() ,因为 set() 和 show() 此时已经变为了派生类中的私有成员函数。




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2