C++中public、protected、private的权限总结

1. 访问权限总结

  • 当存在继承时
    • 子类成员函数: 
      • 可以访问父类的public和protected成员
      • 不可访问父类的private成员
    • 子类实例
      • public继承的子类实例可访问父类的public成员,不可访问private和protected成员
      • protected与private继承的子类实例不可访问父类的任何成员
      • 综上,子类实例访问父类成员,只有一种情况:public继承的子类访问父类中的public成员

画个表格更清晰:

实验代码如下:

#include <iostream>
using namespace std;

#define MEMBER_FUNCTIONS_FOR_PRINTING_ALL_KINDS_OF_MEMBERS                         \
public:                                                                            \
    void printBase() {                                                             \
        cout << baseDataInPublic << endl;                                          \
        cout << baseDataInProtected << endl;                                       \
                                                                                   \
        protected_print_public_base();                                             \
        protected_print_protected_base();                                          \
        private_print_public_base();                                               \
        private_print_protected_base();                                            \
                                                                                   \
        A_public_print();                                                          \
        A_protected_print();                                                       \
    }                                                                              \
                                                                                   \
protected:                                                                         \
    void protected_print_public_base() {cout << baseDataInPublic << endl; }        \
    void protected_print_protected_base() {cout << baseDataInProtected << endl; }  \
                                                                                   \
private:                                                                           \
    void private_print_public_base() {cout << baseDataInPublic << endl; }          \
    void private_print_protected_base() {cout << baseDataInProtected << endl; }
 
class A
{
public:
    A(int a, int b, int c) : 
        baseDataInPublic(a), baseDataInProtected(b), baseDataInPrivate(c) {}
    
public:
    int baseDataInPublic;
    void A_public_print() { cout << baseDataInPublic << endl; }
    
protected:
    int baseDataInProtected;
    void A_protected_print() { cout << baseDataInProtected << endl; }
    
private:
    int baseDataInPrivate;
    void A_private_print() { cout << baseDataInPrivate << endl; }
};
 
class B : public A 
{
public: 
    B(int a, int b, int c) : A(a, b, c) {}
    ~B(){}
    
MEMBER_FUNCTIONS_FOR_PRINTING_ALL_KINDS_OF_MEMBERS
};

class C : protected A 
{
public: 
    C(int a, int b, int c):A(a, b, c) {}
    ~C(){}
    
MEMBER_FUNCTIONS_FOR_PRINTING_ALL_KINDS_OF_MEMBERS
};
 
class D : private A 
{
public:
    D(int a, int b, int c):A(a, b, c){}
    ~D(){}
    
MEMBER_FUNCTIONS_FOR_PRINTING_ALL_KINDS_OF_MEMBERS
};
 
 
int main()
{
    B *pb = new B(10, 20, 30); 
    C *pc = new C(10, 20, 30); 
    D *pd = new D(10, 20, 30); 
    
    cout << "Access member variable by member function...\n";
    
    cout << "Public Herit: \n";
    pb->printBase();
    
    cout << "Protected Herit: \n";
    pc->printBase();
    
    cout << "Private Herit: \n";
    pd->printBase();
    
    // Only public heritage's Base class's public members can be accessed 
    cout << "Access members directly...\n";  
    cout << pb->baseDataInPublic << endl; 
    pb->A_public_print();
    // pb->A_protected_print();                 // Cannot access 
    // cout << pc->baseDataInPublic << endl;    // Cannot access 
    // cout << pd->baseDataInPublic << endl;    // Cannot access
    
    return 0;
}

以上是访问权限总结。

2. 父类成员在子类中是什么类型

关于“父类成员在子类中是什么类型的成员”,可参见下表:

父类public成员父类protected成员父类private成员
public继承子类public成员子类protected成员不可见
protected继承子类protected成员子类protected成员不可见
private继承(默认)子类private成员子类private成员不可见

对上表可做2点总结:

  • 父类的private成员对任何继承方式的子类都是不可见的;
  • 其他情况,总是依据“类的继承类型”和“该成员在父类中的类型”这二者选择更严格的一种来作为“父类成员在子类中的成员类型”。

3. Protected关键字的作用

那么,protected关键字有什么重要作用呢?

依据笔者个人的经验和理解,有2个作用:

1. 如果想一个类只能成为父类,而不想它有任何对象,则可以将其构造函数声明为protected的 (因为如果是public的,则可以有自己的对象;而如果是private的构造函数,则无法有子类,因为子类无法构造父类的部分。)

2. protected继承和private继承都能够使得多态不存在。

见如下代码:

class A {
public:
    virtual void f() {}
};

class B : protected A 
{};

int main()
{
    A* pa = new B();  // 此句编译不通过

    return 0;
}

因为B对于A来说是不可访问的父类。

这个特性在一些实现中还是很有用处的,主要就是可以避免误用多态。

最后,其实protected和private继承,大约主要还是用在库编程和模板编程中。有文章统计过一些热门的C++项目,极少用到private和protected继承,用了的也大多是和模板库相关的。不过作为知识结构的一部分,还是有必要有较深刻理解的。

[2022-01-09] 更新

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值