赞
踩
c++和java都是面向对象的语言,具有封装、继承、多态三大特性
多态就是不同继承关系的类对象,去调用同一函数,产生了不同的行为
class Base { public: void print(int a) const{ cout << "Class Base" << endl; } }; class Base1:public Base { public: void print(int a,int b) const { cout << "Class Base1" << endl; } void addFunction() const { cout << "派生类的新增函数" << endl; } }; int main() { Base base_x; //基类对象 Base1 base1_x; //派生类对象 base1_x.print(1,2); //输出“Class Base1” base1_x.print(1); //报错,函数不接受一个参数。说明父类void print(int a)函数被隐藏 base1_x.Base::print(); //输出“Class Base” base_x.print(); //输出“Class Base” base_x = base1_x; //将派生类对象赋值给基类对象 base_x.print(1); //输出“Class Base” //因为c++默认函数调用是静态绑定,最后调用基类对象时看的是声明类型Base,绑定调用基类中的函数。 Base *base_p; base_p = &base1_x; //将派生类对象地址赋值给基类指针 base_p->print(1); //输出“Class Base” Base &base_r=base1_x; //派生类对象初始化基类引用 base_r.print(1); //输出“Class Base” //basex.addFunction(); 报错,派生类新增成员不能访问 }
#include<iostream> using namespace std; class Base { public: virtual void print(int a) const{ cout << "Class Base" << endl; } }; class Base1:public Base { public: //下面两个print都对基类print函数进行了重写,且这两个print互为重载 virtual void print(int a) const { //virtual可省略,继承于Base cout << "Class Base1" << endl; } virtual void print(int a,int b) const { //virtual可省略,继承于Base cout << "Class Base1 two" << endl; } void addFunction() const { cout << "派生类的新增函数" << endl; } }; int main() { Base basex; Base1 base1x; base1x.print(1); //输出“Class Base1” base1x.Base::print(1); //输出“Class Base” basex.print(1); //输出“Class Base” basex = base1x; //将派生类对象赋值给基类对象 basex.print(1); //输出“Class Base” basex.print(1,2); //报错,基类对象仍然是静态绑定 //basex.addFunction(); Base* basep; basep = &base1x; //将派生类对象地址赋值给基类指针 basep->print(1); //输出“Class Base1” basep->addFunction(); //报错,addFunction()不是从基类中继承下来的虚函数,所以仍然不能调用 Base& baser = base1x; //派生类对象初始化基类引用 baser.print(1,2); //输出“Class Base1 Two” }
public class Test1 { public static void main(String[] args) { Base basex = new Base(); //基类对象 Base1 base1x = new Base1(); //派生类对象 base1x.print(); //输出“Class Base1” base1x.print(1); //输出“Class Base1但是重载” base1x.fun(); //输出“fun Base1” base1x.ifBaseChanged(); //输出“Class Base”,说明方法重写只是在子类中进行方法重写,不会改变父类中的方法 basex.print(); //输出“Class Base” basex.fun(); //输出“fun Base”; basex = base1x; //引用传递 basex.print(); //输出“Class Base1” base1为basex的实际类型,调用base1的print方法 basex.fun(); //输出“fun Base” fun是静态方法无法进行动态绑定,所以仍然输出声明类型的方法 //basex.ifBaseChanged(); 报错,不可以访问 } } class Base{ public void print() { System.out.println("Class Base"); } static void fun() { System.out.println("fun Base"); } } class Base1 extends Base{ @Override public void print() { System.out.println("Class Base1"); } public void print(int a) { System.out.println("Class Base1但是重载"); } public void ifBaseChanged() { super.print(); } static void fun() { System.out.println("fun Base1"); } }
c++允许多继承
#include<iostream> using namespace std; class Base { public: void setX(int x) { this->x = x; } int getX() const{ return x; } private: int x; }; class Base1 :public Base { public: void setY(int y) { this->y = y; } int getY() const{ return y; } private: int y; }; class Base2 :public Base { public: void setZ(int z){ this->z = z; } int getZ() const { return z; } private: int z; }; class Derived :public Base1, public Base2 { }; int main() { Derived d; d.Base1::setX(111); cout << d.Base1::getX() << endl; d.Base2::setX(222); cout << d.Base2::getX() << endl; return 0; }
class Base { public: Base(int x) { this->x = x; } void setX(int x) { this->x = x; } int getX() const{ return x; } private: int x; }; class Base1 :virtual public Base { public: Base1(int y) :Base(y) { this->y = y; } void setY(int y) { this->y = y; } int getY() const{ return y; } private: int y; }; class Base2 :virtual public Base { public: Base2(int z) :Base(z) { this->z = z; } void setZ(int z){ this->z = z; } int getZ() const { return z; } private: int z; }; class Derived :public Base1, public Base2 { public: Derived(int value) :Base(value), Base1(value), Base2(value){} }; int main() { Derived d(111); d.setX(111); cout << d.getX() << endl; return 0; }
如果虚基类中没有无参构造函数,只有有参构造函数,则在类层次结构中,直接或间接继承虚基类的所有派生类都必须在构造函数初始化列表中显示调用虚基类的有参构造函数。
纯虚函数是在基类中声明的没有函数体的虚函数。含有纯虚函数的类称为抽象类,抽象类只能作为其他类的基类,所以又称抽象基类
不能创建抽象类对象,但可以声明抽象类指针或抽象类引用,指向或引用其派生类对象。
建立抽象类的目的就是为了多态地使用其中的纯虚函数
class Shape{
public:
virtual double getArea() = 0;
virtual double getPerimeter() = 0;
}
与c++抽象类定义类似,在基类中声明但没有函数体的方法,称为抽象方法,用abstract修饰,而含有抽象方法的基类称为抽象类,类的头部也要用abstract修饰。抽象类的构造方法定义为protected,因为它只被子类使用。创建抽象类的目的同样是为了多态地调用抽象方法。
子类可以重写父类的方法并将它定义为抽象的,这很少见,但是当父类的方法实现在子类中变得无效时,子类必须定义为抽象的。
java不能多继承,所以java通过接口来实现类似于多继承的功能。抽象类可以包括它子类的共同特征,而子类中部分子类有自己的共同特征,此时可以用到接口。接口是一种与类相似的结构,用于指明相关或不相关类的对象的共同行为。
为了区分接口和类,java采取下面的语法来定义接口:
public interface Edible{
public abstract String howToEat();
}
用关键词implement让对象所属的类来实现这个接口。类和接口之间的关系称为:接口继承。
class Chicken extends Animal implements Edible{ @Override public String hoeToEat(){ return "Chicken: Fry it"; } } class Tiger extends Animal{ } abstract class Fruit implements Edible{ } class Apple extends Fruit{ @Override public String hoeToEat(){ return "Apple:Make apple cider"; }
接口中所有方法都是public abstract,所有的数据域都是public static final。
一个类可以实现多个接口,但只能继承一个父类
同时接口也可以继承其他接口,这样的接口称为子接口,但是接口不能继承类
所有的类共享一个根类Object,但是接口没有共同的根。
一般来说,清晰描述父子关系的“是…的一种”关系,使用类,而用来描述行为动作,表明对象拥有某种属性的,使用接口。
通常推荐使用接口而非抽象类,因为接口可以为不相关类定义共同的父类型。接口比类更加灵活。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。