是的,我确实理解它们之间的区别.我想知道的是:为什么OVERRIDE一个方法?这样做有什么好处?在超载的情况下:唯一的优点是你不必用不同的名称思考功能?
重载通常意味着您在同一作用域中具有两个或多个具有相同名称的函数.在进行调用时更好地匹配参数的函数获胜并被调用.需要注意的是,与调用虚函数相反,重要的是在编译时选择被调用的函数.这一切都取决于参数的静态类型.如果你有一个重载for B
和一个for D
,并且参数是一个引用B
,但它确实指向一个D
对象,那么B
在C++中选择了重载.与动态调度相反,这称为静态调度.如果要与具有相同名称的另一个函数执行相同操作,则需要重载,但是您希望对另一个参数类型执行此操作.例:
void print(Foo const& f) { // print a foo } void print(Bar const& bar) { // print a bar }
他们都打印他们的论点,所以他们超负荷.但第一个打印foo,第二个打印一个条形码.如果你有两个不同的功能,当它们具有相同的名称时,它被认为是不好的风格,因为这会导致混淆实际调用函数时会发生什么.另一个用于重载的用例是当你有函数的附加参数时,它们只是将控制权转发给其他函数:
void print(Foo & f, PrintAttributes b) { /* ... */ } void print(Foo & f, std::string const& header, bool printBold) { print(f, PrintAttributes(header, printBold)); }
如果经常使用重载所采用的选项,那对于调用者来说这将是方便的.
覆盖是完全不同的东西.它不会与超载竞争.这意味着如果在基类中有虚函数,则可以在派生类中编写具有相同签名的函数.派生类中的函数会覆盖基类的函数.样品:
struct base { virtual void print() { cout << "base!"; } } struct derived: base { virtual void print() { cout << "derived!"; } }
现在,如果你有一个对象并调用print
成员函数,则总是调用derived的print函数,因为它会覆盖其中一个.如果函数print
不是虚函数,则派生函数不会覆盖基函数,但只会隐藏它.如果您有一个接受基类的函数,并且每个函数都是从它派生的,那么重写可能很有用:
void doit(base &b) { // and sometimes, we want to print it b.print(); }
现在,即使在编译时编译器只知道b至少是base,也会调用派生类的print.这就是虚拟功能的关键.如果没有它们,将调用基类的print函数,派生类中的函数不会覆盖它.
这将为思想增添更多清晰度.
你过度加载函数有三个原因:
提供执行类似的,密切相关的事物的两个(或更多)函数,由它接受的参数的类型和/或数量来区分.举例:
void Log(std::string msg); // logs a message to standard out void Log(std::string msg, std::ofstream); // logs a message to a file
提供两种(或更多种)方法来执行相同的操作.举例:
void Plot(Point pt); // plots a point at (pt.x, pt.y) void Plot(int x, int y); // plots a point at (x, y)
给出两种(或多种)不同输入类型执行等效操作的能力.举例:
wchar_t ToUnicode(char c); std::wstring ToUnicode(std::string s);
在某些情况下,值得争辩的是,不同名称的函数比重载函数更好.在构造函数的情况下,重载是唯一的选择.
过骑的功能是完全不同的,并且用于完全不同的目的.函数重写是多态在C++中的工作原理.您重写一个函数以更改派生类中该函数的行为.通过这种方式,基类提供接口,派生类提供实现.