cpp►vs JAVA继承 及多态

本文对比了Java和C++中的类继承与多态实现,包括Animal和Dog类的实例、构造函数调用、私有成员访问、虚函数应用,以及多态性在引用类型的体现。通过实际代码展示,深入理解这两个概念在编程中的关键作用。
摘要由CSDN通过智能技术生成

JAVA版类继承及多态
public class Animal {
	private String name;
	private int age;
	private String food;
	
	public Animal(String name, int age, String food) {
		this.name = name;
		this.age = age;
		this.food = food;
	}
	
	public String getName() {// 成员函数当然能访问private成员了
		return name;
	}
	public int getAge() {
		return age;
	}
	public String getFood() {
		return food;
	}
	
	public void eat() {
		System.out.println(name + " is " + age + " years' old, and eat " + food);
	}
}
public class Dog extends Animal {
	private String behavior;// 添加一个成员
	
	public Dog(String name, int age, String food, String behavior) {
		super(name, age, food);// 不可删除此行!(为完成初始化)
		this.behavior = behavior;
	}

	@Override
	public void eat() {// 重写父类方法
		System.out.println("name=" + getName() + ", age=" + getAge() + ", food=" + getFood() + ", behavior=" + behavior);
	}

	public String getBehavior() {// 添加一个方法
		return behavior;
	}
}
public class Test {
	public static void main(String[] args) {
		Animal animal = new Dog("小灰", 8, "bone", "bark");
		animal.eat();
	}
}
name=小灰 ,age=8 ,food=bone ,behavior=bark

Dog类[构造函数]如果注释掉super(name, age, food);,则会报错:

即:隐式super构造函数Animal()未定义——没定义默认空构造函数。 必须显式地调用另一个构造函数!不然的话,name、age、food成员变量没法初始化。如果定义了Animal()默认空构造函数,去掉super(…),当然编译能通过,不会报错,只是name、age、food成员没法初始化,意义就不大了。
可以看到,在子类是没法直接访问super类的private成员的,但可以直接调用public方法,如getName()、getAge()、getFood()。当然,子类也可以重载父类方法,如eat()。

C++类继承及多态
#include <string>
#include <iostream>
using namespace std;
class Animal {
private:
	string name;
	int age;
	string food;
public:
	Animal(const string& n = "none", const int& a = 0, const string& f = "none");
	string getName() const { return name; }
	int getAge() const { return age; }
	string getFood() const { return food; }
	void eat() const;// ★改正:应加上virtual关键字,成为虚函数!
};

Animal::Animal(const string& n, const int& a, const string& f) :
	name(n), age(a), food(f) {}

void Animal::eat() const {
	cout << name << " is " << age << " years' old, and eat " << food;
}

class Dog : public Animal {
private:
	string behavior;// 添加一个成员
public:
	Dog(const string& n = "none", const int& a = 0, const string& f = "none", string b = "none");
	Dog(string b, const Animal& animal);
	void eat() const;// ★改正:应加上virtual关键字,成为虚函数!
	string getBehavior() const {// 添加一个函数
		return behavior;
	}
};

Dog::Dog(const string& n, const int& a, const string& f, string b) : Animal(n, a, f) {
	behavior = b;
}
Dog::Dog(string b, const Animal& animal) : Animal(animal) {
	behavior = b;
}
void Dog::eat() const {
	cout << "name=" + getName() << ", age=" + getAge() << ", food=" + getFood() << ", behavior=" + behavior;
}

int main() {
	Dog dog("小灰", 8, "bone", "bark");
	Animal animal = dog;// ★改正:animal应该是引用类型而不能是值类型,因为多态一定是引用或指针才能完成的。
	ref.eat();
	return 0;
}
小灰 is 8 years' old, and eat bone

明明子类重写了父类的eat()函数,为什么还是调用的是父类的eat()函数呢?
这里就得涉及virtual关键字了。虚方法的行为会根据对象类型来选择。

经常在基类中将派生类会重新定义的方法声明为虚方法。方法在基类中被声明为虚的后,它在派生类中将自动成为虚方法。然而,在派生类声明中使用关键字virtual来指出哪些函数是虚函数也不失为一个好办法。

如果要在派生类中重新定义基类的方法,通常应将基类方法声明为虚的。这样,程序将根据对象类型而不是引用或指针的类型来选择方法版本。为基类声明一个虚析构函数也是一种惯例。

按代码中★号开头的注释去处理,就如期正常运行了。
多态一定是引用或指针才能完成的。

virtual void eat() const;// 多态需求,虚函数必须!否则不成功。

Animal& animal = dog;// 多态需求,父类必须是引用类型!否则不成功。

运行结果如期望的:

name=小灰 ,age=8 ,food=bone ,behavior=bark
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

itzyjr

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

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

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

打赏作者

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

抵扣说明:

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

余额充值