【C++多态篇】多态调用和普通调用

多态调用和普通调用

C++中只有两个调用关系,分为普通调用多态调用。不满足多态调用就是普通调用。

多态必须构成的两个条件

  1. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写(也就是必须满足重写)
  2. 必须通过基类的指针或者引用调用虚函数(指针和引用)
多态调用:跟指向的对象有关,传的对象是谁的,调用的就是谁的。
普通调用:和类型有关。类型是什么调用就是什么,类型是Person的,那么调用的函数就是Person的。 比如下面的例子。

普通调用的例子:

class A {};
class B : public A{};
class Person{
public: 
	virtual B*f(){
		cout << "Person::f()" << endl;
		return new B;
		}
};
class Student: public Person{
public:
	virtual B* f(){
		cout << "Student::f()" << endl;
		return new B;
		}
};
int main ()
{
	Person p;
	p.f();
	Student s;
	p = s;       //派生类赋值给子类
	p.f();
   
    system("pause");
}

结果
在这里插入图片描述
分析
在这里虽然调用的是虚函数,派生类中也对基类的虚函数进行了重写。但是不是使用基类的指针或引用调用,所以不满足多态调用的条件。
所以在这里是普通调用。只与类型有关,尽管Student对象s赋值给父类对象p,但是普通调用只与类型有关,所以仍然调用p的f()函数

多态调用的例子

class A {};
class B : public A{};
class Person{
public: 
	virtual B*f(){
		cout << "Person::f()" << endl;
		return new B;
		}
};
class Student: public Person{
public:
	virtual B* f(){
		cout << "Student::f()" << endl;
		return new B;
		}
};
int main()
{
	Person p;
	Student s;
	Person* ptr = &p;
	//本来就是Person类的指针,指向Person类的对象,调用的本来就是Person父类的f()函数
	ptr->f() ; 
	
	ptr = &s;
	ptr->f(); //指向的是子类的对象, 调用的是子类的f()的函数
}

结果
在这里插入图片描述
分析
在这里被调用的是虚函数,且派生类Student里对虚函数f()进行了重写。又是基类的指针对虚函数的调用,所以满足多态调用。
ptr是基类的指针,指向的是派生类的对象, 基类的指针调用虚函数,构成多态调用,只和对象有关。所以调用的是派生类的f()函数。

错误多态调用的例子

值得注意的一点: 必须是基类的指针对虚函数的调用,下面有一个派生类指针对虚函数的调用

class A {};
class B : public A{};
class Person{
public:
	virtual B*f(){
		cout << "Person::f()" << endl;
		return new B;
	}
};
class Student : public Person{
public:
	virtual B* f(){
		cout << "Student::f()" << endl;
		return new B;
	}
};
int main()
{ 
	Student s;
	// 派生类指针指向派生类的对象,调用虚构函数,肯定是调用自己的,因为自己完成了对虚函数的重写
	Student* ps = &s; 
	ps->f();

	cout << endl;

	Person p;
	Person* ptr = &p;  // Person类的指针, 指向Person类的对象,调用的本来就是Person类的虚函数
	ptr->f();
	cout << endl;

	ps = (Student*)ptr;   //将基类Person的指针强转 赋给派生类Student的指针ps
	ps->f();         //派生类的指针调用虚函数, 所以不构成重写, 不满足多态调用。 所以和对象没有关系,只与类型有关系
	system("pause");
}

结果:
在这里插入图片描述
分析:
在这里看最后一个输出的Person::f()。
将基类Person的指针强转赋给派生类Student的指针ps。
派生类的指针调用虚函数, 所以不构成重写, 不满足多态调用。 所以和对象没有关系,只与类型有关。 在这里ptr是Person * 类型的,是强转成Student * 类型的, 所以输出的只与类型有关, 输出Person * 的f(). 所以输出的是Person->f()

发布了55 篇原创文章 · 获赞 12 · 访问量 5239

猜你喜欢

转载自blog.csdn.net/weixin_43939593/article/details/103664573