C++ -- 重载、重定义、重写的区别

一.重载
1.在同一个作用域下,函数名相同,函数的参数不同(参数不同指参数的类型或参数的个数不相同)
2.不能根据返回值判断两个函数是否构成重载。
3.当函数构成重载后,调用该函数时,编译器会根据函数的参数选择合适的函数进行调用。
4.构成重载的例子:
#include
using namespace std;
int Add( int a , int b )
{
       return a + b ;
}
double Add( double a , double b )
{
       return a + b ;
}
int main()
{
      cout << Add(3, 4) << endl;   
      cout << Add(3.1, 4.1) << endl;
      system( "pause" );
       return 0;
}
5.运行结果:
C++ -- 重载、重定义、重写的区别_第1张图片
二.重定义(隐藏)
1.在不同的作用域下(这里不同的作用域指一个在子类,一个在父类 ),函数名相同的两个函数构成重定义。
2.当两个函数构成重定义时,父类的同名函数会被隐藏,当用子类的对象调用同名的函数时,如果不指定类作用符,就只会调用子类的同名函数。
3.如果想要调用父类的同名函数,就必须指定父类的域作用符。
注意:当父类和子类的成员变量名相同时,也会构成隐藏。
4.隐藏的例子:
(1)定义一个B的对象b,当访问同名的函数fun1时,不指定域,会默认访问子类的fun1。
C++ -- 重载、重定义、重写的区别_第2张图片
(2) 定义一个B的对象b,当访问同名的函数fun1时,指定域为A,则会访问父类的fun1。
C++ -- 重载、重定义、重写的区别_第3张图片
(3)将父类与子类的同名函数fun1进行如下改写,使这两个函数的参数不同,
class A
{
public :
       void fun1( char c )
      {
           cout << "A::fun1()" << endl;
      }
       int _a;
};
class B : public A
{
public :
       void fun1( int a , int b )
      {
           cout << "B::fun1()" << endl;
      }
       int _b;
};
int main()
{
       B b;
      b.fun1( 'a' );
      system( "pause" );
       return 0;
}
当定义B的对象b,调用与父类参数相同的同名函数时会出现错误,因为子类隐藏了父类的同名成员函数,不指定域,只会调用子类的同名成员函数,而传的参数与子类同名成员函数的参数不同,所以会编译失败
C++ -- 重载、重定义、重写的区别_第4张图片 当指定作用域时,就会调用父类的同名函数
C++ -- 重载、重定义、重写的区别_第5张图片
三.重写(覆盖)
1.在不同的作用域下(一个在父类,一个在子类),函数的函数名、参数、返回值完全相同,父类必须含有virtual关键字(协变除外)。
2.什么是协变?
(1)函数的函数名相同,参数也相同,但是函数的返回值可以不同(但必须只能是一个返回父类的指针(或引用)一个返回子类的指针(或引用),父类必须含有virtual关键字。
(2)构成协变的一种方式,返回指针;
class A
{
public :
       virtual A * func1()
      {
           cout << "A::func1()" << endl;
            return this ;
      }
private :
       int _a;
};
class B : public A
{
public :
       virtual A * func1()
      {
           cout << "B::func1()" << endl;
            return this ;
      }
private :
       int _b;
};
int main()
{
       A a;
       B b;
       A * p = &a;   //多态的场景
      p->func1();
      p = &b;
      p->func1();
      system( "pause" );
       return 0;
}
则运行结果如下:(因为是父类对象的指针,由包含协变,所以构成多态,指向父类调父类指向子类调子类)
C++ -- 重载、重定义、重写的区别_第6张图片
(3)构成协变的另一种方式,返回引用;
class A
{
public :
       virtual A & func1()
      {
           cout << "A::func1()" << endl;
            return * this ;
      }
private :
       int _a;
};
class B : public A
{
public :
       virtual A & func1()
      {
           cout << "B::func1()" << endl;
            return * this ;
      }
private :
       int _b;
};
int main()
{
       A a;
       B b;
       A * p = &a;
      p->func1();
      p = &b;
      p->func1();
      system( "pause" );
       return 0;
}
运行结果如下,仍然构成多态
C++ -- 重载、重定义、重写的区别_第7张图片
3.构成重写的代码:
class A
{
public :
       virtual void func1()
      {
           cout << "A::func1()" << endl;
      }
private :
       int _a;
};
class B : public A
{
public :
       virtual void func1()
      {
           cout << "B::func1()" << endl;
      }
private :
       int _b;
};
int main()
{
       A a;
       B b;
       A * p = &a;
      p->func1();
      p = &b;
      p->func1();
      system( "pause" );
       return 0;
}

你可能感兴趣的:(C++)