文章

c++(5·访问修饰符、重写隐藏重载、友元)

成员访问修饰符

作用

控制着类成员的访问 == 调用权限

分类:

  • public公共:在类内,类外(类定义外),派生类,友元,都可以访问,通常存放对外公开的接口
  • protected受保护:在类内,派生类,友元可以访问,通常存放在继承体系中可以访问的部分
  • private私有:只能在类内,友元,可以访问,通常存放对类外隐藏实现的部分

访问修饰符和继承:

注意:访问修饰符并不会影响派生类是否可以 继承/隐藏/重写(即使是private的),只是影响是否能被访问

继承 vs. 重写 vs. 隐藏 vs. 重载

区别:

  • 继承:
    • 派生类没有重新定义基类方法,不包含任何/仅声明
    • 对于构造,析构……特殊的成员,并不会继承,而是会生成默认的函数
    • 如果基类的析构函数是虚析构函数,那么派生类的析构函数也会自动成为虚析构函数
  • 重写/覆盖:
    • 不同作用域,
    • 基类的virtual,
    • 派生类 同名,同返回类型,同形参列表
    • 支持多态
  • 隐藏:
    • 不同作用域,
    • 基类没有virtual,
    • 派生类 同名,其中返回类型,形参列表 可以不同,可以隐藏掉基类所有同名函数
    • 不支持多态
  • 重载:
    • 相同作用域,
    • 同名,参数列表不同,返回类型可以相同也可以不同

覆盖 vs. 隐藏 的字面意思

  • 重写/覆盖:强调拷贝再重写,因为都没有被遮住,可以在任意时刻选择任意版本的
  • 隐藏:强调遮蔽再重写,如果选择基类,就只能查看基类部分,因为派生类被遮住

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base {
public:
    void func() {}
    void func1() {}
    void func1(float x) {}  
private:  
    void func(int x) {}
    void func1(int x) {}  
    virtual void func2() {}
};

class Derived : public Base {
public:
    void func1() {}
    void func2() {}
};

展开

上述流程:

  • func:
    • base中定义了2个重载版本,都会被Derived继承,
    • 由于第2个版本为private,因此不能被derived调用
  • func1:
    • base中定义了3个重载版本,都会被Derived隐藏,
    • 当在derived内直接调用func1时只能调用derived中的func1版本,但可以Base::func1 (作用域解析运算符)显式调用基类中的版本,
    • base private的部分不能被外部调用,但是base public部分可以被外部调用,derived部分可以被外部调用
  • func2:
    • base中定义了1个版本,会被Derived重写,
    • 外部代码不能通过基类指针/引用直接调用 private virtual 方法,即使实际类型是派生类对象,且在派生类中修改权限为private(可以用于“不想对外暴露 virtual 函数,而提供一个 public 的非虚函数给外界访问”的情形)
    • 如果想要在外面调用,基类以及派生类必须都为public的
    • 如果仅想调用派生类public virtual func2的,则需要创建派生类对象调用

继承访问修饰符

作用

控制派生类对象对基类成员的访问权限

分类

private部分由于没有访问权限所以我们直接忽略

  • public 继承:基类的 public 和 protected 成员在派生类中保持原有访问权限
  • protected 继承:基类的 public 和 protected 成员在派生类中变为protected
  • private 继承(默认):基类的 public 和 protected 成员在派生类中变为private

友元

作用:

通过friend声明为友元,允许某个外部函数/类访问当前类的 private 和 protected 成员

分类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Box {
public:
    Box(int w) : width(w) {}
    // 声明友元函数
    friend void printWidth(Box box);
    // 声明友元类
    friend class Printer;
private:
    int width;
};

void printWidth(Box box) {
    cout << "Box width: " << box.width << endl;
}
class Printer {
public:
    void printWidth(Box box) {
        cout << "Box width: " << box.width << endl;
    }
};

展开

  • 友元函数:
  • 友元类:

特点:

  • 友元关系是单向的,如果 A 是 B 的友元,B 是 C 的友元,A 不会自动成为 C 的友元
  • 不能继承,基类的友元不是派生类的友元
  • 不受访问修饰符影响,friend 声明可以放在 public、protected 或 private 区域,不影响其友元的性质
本文由作者按照 CC BY 4.0 进行授权
本页总访问量