是否构成多态的条件:
1、父类的指针或引用
2、虚函数的重写
是否构成虚函数的条件:
1、有virtual
2、函数完全相同(协变:返回值可以不同,但返回值是父子关系的引用或指针)
#include <iostream>
using namespace std;
//基类
class Person
{
public:
virtual void BuyTickets()
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()
{
cout << "买小孩票" << endl;
}
};
void Fun(Person& p)
{
p.BuyTickets();
}
// 构成多态,和类型无关,和对象有关
void Test()
{
Person p;
Student s;
Fun(p);
Fun(s);
}
int main()
{
Test();
system("pause");
return 0;
}
输出:
买成人票
买小孩票
--------------------------------------------------------
去掉基类的virtual
#include <iostream>
using namespace std;
//基类
class Person
{
public:
void BuyTickets()// 去掉virtual,构不成多态,就和类型有关,p是基类的就全部调的是基类
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()
{
cout << "买小孩票" << endl;
}
};
输出:
买成人票
买成人票
------------------------------------------------------
去掉子类的virtual
#include <iostream>
using namespace std;
//基类
class Person
{
public:
virtual void BuyTickets()//
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
void BuyTickets()// 只去掉子类的virtual,还是会构成多态,因为子类继承父类,输出和第一次一样
{
cout << "买小孩票" << endl;
}
也就是说主要看基类加不加virtual,如果基类加virtual则构成多态,效果和对象有关;如果基类不加virtual则不构成多态,效果和类型有关。
-----------------------------------------------
如果返回值不同:
父类为int,子类为void
class Person
{
public:
virtual int BuyTickets()//
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()//
{
cout << "买小孩票" << endl;
}
};
会弹出一个错误:返回类型与重写虚拟函数 "Person::BuyTickets" 的返回类型 "int" 既不相同,也不协变
协变:当返回值不同,但返回值必须构成子类和父类的关系的指针或引用
协变的例子如下所示:
class Person
{
public:
virtual Person* BuyTickets()//
{
cout << "买成人票" << endl;
return this;
}
};
//派生类
class Student:public Person
{
public:
virtual Student*BuyTickets()//
{
cout << "买小孩票" << endl;
return this;
}
};
这里的Person* 和Student*不一定必须是这俩,只要能构成父子关系即可。
1、父类的指针或引用
2、虚函数的重写
是否构成虚函数的条件:
1、有virtual
2、函数完全相同(协变:返回值可以不同,但返回值是父子关系的引用或指针)
#include <iostream>
using namespace std;
//基类
class Person
{
public:
virtual void BuyTickets()
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()
{
cout << "买小孩票" << endl;
}
};
void Fun(Person& p)
{
p.BuyTickets();
}
// 构成多态,和类型无关,和对象有关
void Test()
{
Person p;
Student s;
Fun(p);
Fun(s);
}
int main()
{
Test();
system("pause");
return 0;
}
输出:
买成人票
买小孩票
--------------------------------------------------------
去掉基类的virtual
#include <iostream>
using namespace std;
//基类
class Person
{
public:
void BuyTickets()// 去掉virtual,构不成多态,就和类型有关,p是基类的就全部调的是基类
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()
{
cout << "买小孩票" << endl;
}
};
输出:
买成人票
买成人票
------------------------------------------------------
去掉子类的virtual
#include <iostream>
using namespace std;
//基类
class Person
{
public:
virtual void BuyTickets()//
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
void BuyTickets()// 只去掉子类的virtual,还是会构成多态,因为子类继承父类,输出和第一次一样
{
cout << "买小孩票" << endl;
}
};
这里总结一个基类和子类加不加virtual的效果:
基类 | 子类 | 效果 |
加virtual | 加virtual | 构成多态,与对象有关 |
加virtual | 不加virtual | 构成多态,与对象有关 |
不加virtual | 加virtual | 不构成多态,与类型有关 |
不加virtual | 不加virtual | 不构成多态,与类型有关 |
如果返回值不同:
父类为int,子类为void
class Person
{
public:
virtual int BuyTickets()//
{
cout << "买成人票" << endl;
}
};
//派生类
class Student:public Person
{
public:
virtual void BuyTickets()//
{
cout << "买小孩票" << endl;
}
};
会弹出一个错误:返回类型与重写虚拟函数 "Person::BuyTickets" 的返回类型 "int" 既不相同,也不协变
协变:当返回值不同,但返回值必须构成子类和父类的关系的指针或引用
协变的例子如下所示:
class Person
{
public:
virtual Person* BuyTickets()//
{
cout << "买成人票" << endl;
return this;
}
};
//派生类
class Student:public Person
{
public:
virtual Student*BuyTickets()//
{
cout << "买小孩票" << endl;
return this;
}
};
这里的Person* 和Student*不一定必须是这俩,只要能构成父子关系即可。