【问题标题】:difference between function hiding and overloading函数隐藏和重载的区别
【发布时间】:2021-03-28 12:41:51
【问题描述】:

我找不到函数隐藏和重载之间的任何区别。由于函数隐藏是派生类中存在的函数,并且隐藏了基类的函数。在它们中具有相同的函数名称。 重载:在派生类和基类中具有相同的名称但不同的签名。

class A {
    void print(int);
};
class B: public A {
    void print(float);
};

它是隐藏函数还是重载?

【问题讨论】:

  • 两者都不是。即使我们假设Class 是一个错字并且应该是class,函数是private,并且两个类都没有另一个成员函数或朋友,所以除了它自己之外的任何函数都不能调用这两个函数。
  • @Pi 问题是关于 overloading 与隐藏,而不是 overriding 与隐藏。两个完全不同的概念。

标签: c++ oop visual-c++


【解决方案1】:

函数B::print隐藏父函数A::print

如果你想重载你需要把A::print函数拉入B的作用域:

class B : public A {
public:
    using A::print;  // Pull in (all) A::print symbols into the scope of B

    void print(float);  // Now overloads A::print
};

【讨论】:

    【解决方案2】:

    在范围内定义的名称隐藏在任何外部范围内的同名声明。像这样:

    int name; // global name
    
    void f() {
        int name; // name 1, hides global name
        for (int i = 0; i < 10; i++) }
            int name; // name 2, hides name 1 and global name
            name = 3; // assigns 3 to name 2
        }
        name = 4; // assigns 4 to name 1
    }
    
    int other = name; // copies value of global name into other
    

    当两个或多个具有相同名称的函数被声明在同一范围内时,名称被重载:

    // two functions in global scope:
    void f();
    void f(int);
    
    void g() {
        f();  // ok: calls first version of f
        f(1); // ok: calls second version of f
    }
    

    不同作用域中的定义不定义重载集,因为内部作用域中的声明隐藏了任何外部作用域中的同名。

    class cl1 {
    public:
        // hides global f's:
        void f();
    
        void g() {
            f();  // ok: calls cl1::f()
            f(1); // error: no f takes an int; global f(int) is hidden
        }
    };
    

    当然,在同一作用域中定义多个函数仍然定义了重载,即使在外部作用域中存在具有相同(隐藏)名称的函数。

    class cl2 {
    public:
        // these hide global f's, and provided overloads:
        void f();
        void f(int);
    
        void g() {
            f();  // calls cl2::f()
            f(1); // calls cl2::f(int)
        }
    };
    

    类定义提供了一个新的范围,因此关于名称隐藏和重载的规则适用于类中定义的名称。

    class cl3 : public cl2 {
            void g() {
                f();  // calls cl2::f()
                f(1); // calls cl2::f(int)
            }
        };
    
    class cl4 : public cl2 {
        // hides all f's:
        void f();
    
        void g() {
            f();  // ok: calls cl4::f();
            f(3); // error: no f takes an int; global f(int) and cl2::f(int) are hidden
        }
    };
    
    class cl5 : public cl2 {
        // hides all f's and provides overloads:
        void f();
        void f(int);
    
        void g() {
            f();  // ok: calls cl5::f()
            f(3); // ok: calls cl5::f(int)
        }
    };
    

    您还可以使用与基类中的任何签名都不匹配的签名。毕竟那些基类函数的名字是隐藏的。

    class cl5 : public cl2 {
    public:
        // hides all f's:
        void f(std::string);
    
        void g() {
            f();       // error: no f taking no arguments
            f(3);      // error: no f taking int
            std::string arg("test");
            f(arg); // ok: calls cl5::f(std::string)
        }
    };
    

    最后,如果你想编写一个派生类,为基类中定义的重载函数集添加签名,你必须将这些重载函数的名称添加到派生类中:

    class cl6 : public cl2 {
    public:
        using cl2::f;        // pull cl2::f into current scope
        void f(std::string); // add overload to names from cl2
    
        void g() {
            f();    // ok: calls cl2::f()
            f(3);   // ok: calls cl2::f(int)
            std::string arg("test");
            f(arg); // ok: calls cl6::f(std::string)
        }
    };
    

    【讨论】:

    • 很好的解释。如果你能解释 Argument Dependent Lookup 和 Global Scope,这个解释可能会更有启发性。
    猜你喜欢
    • 2021-01-29
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2012-10-21
    • 2011-03-13
    • 2017-02-07
    相关资源
    最近更新 更多