java赋值兼容原则,多态问题抛出(赋值兼容性原则遇上父类与子类同名函数的时候)...

本文详细探讨了C++中静态编译与动态绑定的多态现象,通过代码示例解释了子类与父类函数重名时的调用规则,以及如何通过virtual关键字实现动态行为。重点讲解了赋值兼容性原则下的意外调用,以及如何利用虚拟函数实现期望的多态效果。
摘要由CSDN通过智能技术生成

首先通过一个段代码来分析

#include

class Parent//定义父类

{

public:

Parent(int a = 0)

{

this->a = a;

}

void print() //注意这里没有加virtual

{

std::cout << "我是父类" << std::endl;

//std::cout << "a:" << a << std::endl;

}

protected:

private:

int a;

};

class Child :public Parent //继承父类

{

public:

Child(int b = 0)

{

this->b = b;

}

void print()//与父类重名函数(这是重写)

{

std::cout << "我是子类" << std::endl;

//std::cout << "b:" << b << std::endl;

}

protected:

private:

int b;

};

void HowToPrint(Parent *p) //父类的指针变量

{

p->print();

}

void HowToPrint(Parent &p)//父类的引用变量

{

p.print();

}

void main()

{

Parent p1;

Child c1;

p1.print();//这里毫无疑问打印父类的print()

c1.print();//子类对象的print()

Parent *p = NULL;

p = &p1;

p->print();//调用父类的打印函数

//赋值兼容性原则遇上父类与子类同名函数的时候

p = &c1;//把子类对象赋值给父类的指针(赋值兼容性原则)

p->print();//我靠不是把子类对象地址赋值了吗,竟然调用父类的print();

//赋值兼容性原则遇上父类与子类同名函数的时候

Parent &myp = c1;//(父类变量引用子类

myp.print();//疯了,引用子类,竟然调用了父类的函数*/

HowToPrint(&c1);//将子类地址赋值给父类指针,通过指针调用print(),我靠.竟然打印的也是父类

HowToPrint(&p1);//这里无疑问打印父类print

HowToPrint(c1);//引用之类,调用print竟然也是打印我是父类

HowToPrint(p1);//引用父类,无疑问打印父类

system("pause");

}

5deda7856d90eed39247adaa4e108f88.png

这就引出多态的问题呢,嗯哼,接下来我来分析此代码

首先应该了解

定义一个子类与一个父类(子类与父类的函数重名问题

1.C/C++是静态编译性语言

在编译时,编译器自动根据指针类型或引用类型判断指向的是一个什么样的对象

2.编译器没有理由报错

3.于是,编译器认为最安全的做法是编译到父类的print函数(父类与子类都有print()函数)

面向对象新需求

如果我传一个父类对象,执行父类的函数

如果我传一个子类的对象,执行子类的函数,可是编译器不支持我

现象产生原因

赋值兼容性原则遇上函数重写,出现了一个现象

也可以说赋值兼容性原则遇上父类与子类同名函数的时候

1.没有理由报错

2.对被调用函数来说

3.在编译器期间,我就确定了这个函数参数是p及父亲类型

#include

class Parent

{

public:

Parent(int a = 0)

{

this->a = a;

}

//如果想要传入什么类型就打印该类型的参数,就使用virtual关键字,在父类加上了关键字,那么就是动态编译

//子类有与父类重名函数,根据传入类型.来进行选择,而不是根据函数参数(静态编译)进行选择

virtual void print()

{

std::cout << "我是父类" << std::endl;

}

protected:

private:

int a;

};

class Child :public Parent

{

public:

Child(int b = 0)

{

this->b = b;

}

void print()

{

std::cout << "我是子类" << std::endl;

}

protected:

private:

int b;

};

void HowToPrint(Parent *p) //3.在编译器期间,我就确定了这个函数参数是p及父亲类型

{ //在这里C++编译器始终认为p是指向父类的指针变量

p->print();//一句话,有多种效果,多种表现形态吧,,这个功能就是传说中的多态

}

void HowToPrint(Parent &p)

{

p.print();

}

void main()

{

Parent p1;

Child c1;

/*-==p1.print();

c1.print();*/

Parent *p = NULL;

p = &p1;

p->print();

p = &c1;

p->print();

Parent &mypk = p1;

p1.print();

Parent &myp = c1;

myp.print();

HowToPrint(&p1);

//兼容性原则

HowToPrint(&c1);

HowToPrint(p1);

//兼容性原则

HowToPrint(c1);

system("pause");

}

7cbf76ef82dea34bdb7309cdc0fc25ad.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值