函数隐藏和重载的区别

问题描述 投票:0回答:3

我找不到函数隐藏和重载之间有什么区别。由于函数隐藏是派生类中存在的函数并隐藏基类的函数。两者的函数名称相同。 重载:在派生类和基类中具有相同的名称但不同的签名。

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

它隐藏了函数或重载吗?

c++ oop visual-c++
3个回答
9
投票

函数

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
};

4
投票

作用域中定义的名称隐藏任何外部作用域中同名的声明。像这样:

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)
    }
};

0
投票

基于上面的答案,当函数隐藏影响跨访问级别的函数时,将父符号拉入子类的

using
功能会引发错误。

class A {
public:
  void f(int i) {f(i * float(1.0));};
private:
  void f(float f) = 0; // use [Template Method pattern](https://refactoring.guru/design-patterns/template-method)
};

class B : public A {
public:
  void f(float); // complete template method in this class
};

编译上述内容将导致任何尝试调用

B::f(int)
的代码出现错误,因为没有找到匹配的函数

还有

class C : public A {
public:
  using A::f; // error, A::f(float) private in parent context
private:
  void f (float);
};

class D : public A {
  using A::f; // error, private parent context AND D::f(int) inaccessible in called context
private: 
  void f (float);
};
© www.soinside.com 2019 - 2024. All rights reserved.