我找不到函数隐藏和重载之间有什么区别。由于函数隐藏是派生类中存在的函数并隐藏基类的函数。两者的函数名称相同。 重载:在派生类和基类中具有相同的名称但不同的签名。
class A {
void print(int);
};
class B: public A {
void print(float);
};
它隐藏了函数或重载吗?
函数
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
};
作用域中定义的名称隐藏任何外部作用域中同名的声明。像这样:
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)
}
};
基于上面的答案,当函数隐藏影响跨访问级别的函数时,将父符号拉入子类的
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);
};