条款33:避免遮掩继承而来的名称

Avoid hiding inherited names.

int x;
void someFunc() {
    double x;
    std::cin >> x;
}

当编译器处于 somFunc 的作用域内并遭遇名称 x 时,它会先在 local 作用域内查找,如果找到就不再找其他作用域。所以 C++ 的名称遮掩规则(name-hiding rules)所做的唯一事情就是:遮掩名称。

derived classes 继承了声明于 base classes 内的所有东西,实际运作方式是,derived class 作用域被嵌套在 base class 作用域内。

不过名称遮掩会同时遮掩掉重载函数:

class Base {
public:
    virtual void mf1() = 0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(int);
};

class Derived: public Base {
public:
    virtual void mf1();
    void mf3();
    void mf4();
};

Derived d;

d.mf1();     // ok,调用 Derived::mf1()
d.mf1(x);    // fail,因为 Derived::mf1() 遮掩掉了 Base::mf1() 和 Base::mf1(int)
d.mf2();     // ok,调用 Base::mf2()
d.mf3();     // ok,调用 Derived::mf3()
d.mf3(x);    // fail,因为 Derived::mf3() 遮掩掉了 Base::mf3() 和 Base::mf3(int)

如果想要继承重载函数,可以使用 using

class Derived: public Base {
public:
    using Base::mf1;
    using Base::mf3;
    virtual void mf1();
    void mf3();
    void mf4();
};

同样地,有时候我们希望 Derived class 不继承全部的函数。这在 public 继承下是不允许的,因为它违反了 public 继承所暗示的 “is-a” 关系。但是在 private 继承下却可能有这样的需求,通常只要一个简单的转交函数(forwarding function):

class Base {
public:
    virtual void mf1() = 0;
    virtual void mf1(int);
};

class Derived: private Base {
public:
    virtual void mf1() {
        Base::mf1();
    }
};

Last updated

Was this helpful?