C++私有继承和保护继承的学习

私有继承

使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。

使用私有继承意味着基类方法将不能在外部直接使用,但可以在派生类的成员函数中使用他们。

保护继承

使用保护继承,基类的公有成员和保护成员都将成为派生类的保护成员。

使用保护继承意味着基类方法将不能在外部直接使用,但可以在派生类的成员函数中使用他们。

实例一

#include <iostream>
#include <string>
// 基类
class Person
{
    private:    // 似有成员
        std::string m_name;   // 姓名
        int m_age;      // 年龄
    protected:   // 保护成员
        int get_age() const 
        {
            return m_age;
        }
    public:     // 公有成员
        Person(const char *name = "", int age = 0)   // 构造函数
            : m_name(name), m_age(age) {}   // 列表成员初始化
        virtual ~Person() {}  // 虚析构函数
        const std::string & get_name() const
        {
            return m_name;
        } 
        friend std::ostream& operator<<(std::ostream &os, const Person& p);     // 友元函数
};

// 派生类
class Student : private Person    // 似有继承
{
    private:
        std::string m_sex;
    public:
        Student(const char *name = "", int age = 0, const char *sex = "female")    // 构造函数
            : Person(name, age),m_sex(sex) {}   // 列表成员初始化
        Student(const Person &p, const char *sex = "female")   // 构造函数
            : Person(p), m_sex(sex) {}  // 列表成员初始化
        int HGetAge() const
        {
            return Person::get_age();
        }
        const std::string & HGetName() const
        {
            return Person::get_name();
        }
        friend std::ostream& operator<<(std::ostream& os, const Student &stu);  // 友元函数
};

// 派生类
class Teacher : protected Person    // 保护继承
{
    private:
        std::string m_subject;
    public:
        Teacher(const char *name, int age, const char *subject = "Chinese") // 构造函数
            : Person(name, age), m_subject(subject) {}
        Teacher(const Person & p, const char *subject = "Chinese")
            : Person(p), m_subject(subject) {}
        int HGetAge() const
        {
            return Person::get_age();
        }
        const std::string & HGetName() const
        {
            return Person::get_name();
        }
        friend std::ostream& operator<<(std::ostream& os, const Teacher &tea);  // 友元函数
};

int main()
{
    using std::cout;
    using std::endl;
    Person p1("zhangsan", 19);
    cout << p1 << endl;
    Student stu1(p1, "man");
    cout << stu1 << endl;
    
    Student stu2("lisi", 18, "female");
    // cout << "Name: " << stu2.get_name() << endl;    // 私有继承,外界不能直接访问私有成员
    cout << "Name: " << stu2.HGetName() << endl;
    cout << "Age: " << stu2.HGetAge() << endl;
    cout << endl;
    
    Teacher t1(p1, "English");
    cout << t1 << endl;
    
    Teacher t2("wangeu", 22, "Math");
    // cout << "Name: " << t2.get_name() << endl;  // 保护继承,外界不能直接访问保护成员
    cout << "Name: " << t2.HGetName() << endl;
    return 0;
}

std::ostream& operator<<(std::ostream &os, const Person& p)     // 友元函数
{
    os << "Name: " << p.m_name << std::endl;
    os << "Age: " << p.m_age << std::endl;
    return os;
}
std::ostream& operator<<(std::ostream& os, const Student &stu)  // 友元函数
{
    os << (Person &)stu;    // 强制类型转换
    std::cout << "Sex: " << stu.m_sex << std::endl;
    return os;
}
std::ostream& operator<<(std::ostream& os, const Teacher &tea)  // 友元函数
{
    os << (Person &)tea;    // 强制类型转换
    std::cout << "Subject: " << tea.m_subject << std::endl;
    return os;
}

程序说明

  1. Student类私有继承了Person类,所有Person中的所有成员在Student中都成为了私有成员,所以外界不能直接访问基类中的公有成员。
  2. Teacher类保护继承了Person类,所有Person中的保护成员和公有成员在Teacher中都成为了保护成员,但基类的私有成员在派生类中仍然为私有成员,所以外界不能直接访问基类中的公有成员。

私有继承和保护继承的区别

当派生类派生出另一个类时,私有继承和保护继承之间的主要区别就出来了。

  • 使用私有继承时,第三代类将不能使用基类的接口,因为基类的公有方法在派生类中将变成私有方法;
  • 使用保护继承时,基类的公有方法在第二代中变成了保护成员,所以第三代派生类可以使用他们。

使用using重新定义访问权限

使用保护继承和私有继承时,基类的公有成员将成为保护成员或私有成员。如果要让基类的方法在派生类外面可用:

  1. 方法一:定义一个使用该基类方法的派生类方法。
const std::string & HGetName() const
{
    return Person::get_name();
}

派生类中定义了一个HGetName()方法来访问基类get_name()方法。

  1. 方法二:将函数调用包装在另一个函数调用中,即使用一个using声明,来指出派生类可以使用特定的基类成员。
class Student : private Person
{
    ...
    public:
        using Person::get_name;
        using Person::get_age;
    ...
};

using声明只是用成员名———没有圆括号、参数和返回值。

实例二

#include <iostream>
#include <string>
// 基类
class Person
{
    private:    // 似有成员
        std::string m_name;   // 姓名
        int m_age;      // 年龄
    protected:   // 保护成员
        int get_age() const 
        {
            return m_age;
        }
    public:     // 公有成员
        Person(const char *name = "", int age = 0)   // 构造函数
            : m_name(name), m_age(age) {}   // 列表成员初始化
        virtual ~Person() {}  // 虚析构函数
        const std::string & get_name() const
        {
            return m_name;
        } 
        friend std::ostream& operator<<(std::ostream &os, const Person& p);     // 友元函数
};

// 派生类
class Student : private Person    // 似有继承
{
    private:
        std::string m_sex;
    public:
        Student(const char *name = "", int age = 0, const char *sex = "female")    // 构造函数
            : Person(name, age),m_sex(sex) {}   // 列表成员初始化
        Student(const Person &p, const char *sex = "female")   // 构造函数
            : Person(p), m_sex(sex) {}  // 列表成员初始化
        using Person::get_age;      // 使用using指出get_age方法可以直接使用
        using Person::get_name;     // 用using指出get_age方法可以直接使用
        int HGetAge() const
        {
            return Person::get_age();
        }
        const std::string & HGetName() const
        {
            return Person::get_name();
        }
        friend std::ostream& operator<<(std::ostream& os, const Student &stu);  // 友元函数
};

int main()
{
    using std::cout;
    using std::endl;
    Person p1("zhangsan", 19);
    cout << p1 << endl;
    Student stu1(p1, "man");
    cout << stu1 << endl;
    
    Student stu2("lisi", 18, "female");
    cout << "Name: " << stu2.HGetName() << endl;
    cout << "Age: " << stu2.HGetAge() << endl;

    cout << "Name: " << stu2.get_name() << endl;    // 私有继承也可以使用基类方法了
    cout << "Age: " << stu2.get_age() << endl;      // 私有继承也可以使用基类方法了
    cout << endl;
    return 0;
}

std::ostream& operator<<(std::ostream &os, const Person& p)     // 友元函数
{
    os << "Name: " << p.m_name << std::endl;
    os << "Age: " << p.m_age << std::endl;
    return os;
}
std::ostream& operator<<(std::ostream& os, const Student &stu)  // 友元函数
{
    os << (Person &)stu;    // 强制类型转换
    std::cout << "Sex: " << stu.m_sex << std::endl;
    return os;
}

程序说明

上述实例中使用using声明使get_age方法和geT_name放在了派生类的公有成员,所以在外界也可以直接使用get_age方法和get_name了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值