C++继承和Java继承的对比+动态联编的注意事项

引入《C++ Primer》P534的概念
静态类型:编译时已知的类型,变量声明或表达式生成时的类型
动态类型: 变量或者表达式在内存中的对象类型

#include <iostream>
using namespace std;
class A {
public:
    void f() {cout << "A\n";}
};
class B :public A {
public:
    B() {}
    void f() {cout << "B\n";}
};
int main()
{
    A a = B();
    a.f();//输出A
}

C++中:
B继承A,B对象向上转型变成A类型对象时,如果调用同名函数(和Java的方法重写有区别),则只能调用A类的函数,因为a被当成了A类型的对象(静态类型是A)
如果被定义为了A类类型还想使用B类的方法,一种办法是声明f()为虚函数,采用指针或者引用调用方法的形式,晚期联编确定调用函数

下面是Java中重写基类函数的调用情况,和java有区别!!

package XXX;
class ABC{
	void f() {
		System.out.println("A");
	}
}
class BD extends ABC{
	void f() {
		System.out.println("B");
	}
}
public class Test 
{
	public static void main(String[] args) 
	{
		ABC a=new BD();
		a.f();//输出B
	}
}

说明:
Java中:如果是上转型对象,则调用B类的重写的方法,有点类似于接口回调

C++中的方法重写的另外一种情况:

#include <iostream>
using namespace std;

class A {
public:
    void f() {
        cout << "A\n";
    }
};
class B :public A {
public:
    B() {

    }
    void f() {
        cout << "B\n";
    }
};
int main()
{
    B b = B();
    b.f();//输出B
    b.A::f();//输出A
    std::cout << "Hello World!\n";
}

如果代码写成:

A b = B();/*即使你b的动态类型是B,但是它被“切片”了,A的复制构造函数把B的基类部分复制了一下,所以b中只有A类的函数和成员*/  
b.B::f();//编译报错,因为A类中没有B类方法f,(静态类型是A且A不是B的派生类)

但是写成

B b=B();/*#3*/
b.A::f();/*静态类型是B但是B类继承了A类的f()所以调用A::f()可以*/

下面动态联编也不起作用,因为A中没有f

class A{};
class B:public A{
public:
	void f(){cout << "B\n";}
};
int main(){
	A* a = &B();
	a->f();//编译报错
}

a的类型已经是A,所以A中没有f,即使你动态联编,在a中也查找不到f,此时编译报错
动态联编的前提是
类中有这个方法才能进行动态联编
稍微修改一下:
就🆗了


#include <iostream>
using namespace std;
class A {
public:
	void f() {
		cout << "A\n";
	}
};
class B :public A {
public:
	
};
int main() {
	B* a = &B();
	a->A::f();//编译通过
}

名称查找规则

在派生类的函数中访问变量或者用对象变量访问函数/成员变量,先在派生类中查找,如果找不到再依次上溯所有父类查找
最后还是找不到再编译报错

所以说
如果你定义的是基类指针,但是调用是调用派生类独有的函数,那么动态联编就起作用前
就已经编译报错了,因为根据名称查找规则,这仅仅在对派生类有效(基类不能向派生类中查找,反过来可行)

总结

根据指针/引用的静态类型
①指针是基类,调用基类函数直接调用,若调用子类方法不能调用,除非声明该函数是虚函数
②指针是派生类,调用基类函数需要用“基类::方法名”调用,若调用派生类,则直接调用即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿维的博客日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值