报错:
C:UsersasusDesktopUntitled2.cpp|26|error: cannot derive from 'final' base 'B' in derived type 'C'
关于重载(overload),重写(override,也称覆盖), 重定义(redefine,也称隐藏):
一、重载(overload)
指函数名相同,但是它的参数表列个数或顺序,类型不同。但是不能靠返回类型来判断。
(1)相同的范围(在同一个作用域中) ;
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
(5)返回值可以不同;
二、重写(也称为覆盖 override)
是指派生类重新定义基类的虚函数,特征是:
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字,不能有 static 。
(5)返回值相同(或是协变),否则报错;<—-协变这个概念我也是第一次才知道…
(6)重写函数的访问修饰符可以不同。尽管 virtual 是 private 的,派生类中重写改写为 public,protected 也是可以的
所以,基本上可以说重载是更广义的复写,因此不再区分重载与复写的区别,一律重载。
三、重定义(也成隐藏)
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)返回值可以不同;
(4)参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载以及覆盖混淆) 。
(5)参数相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆) 。
其实就是覆盖了基类的函数。
(啥?你问我java的final咋弄?)
public:
const ....
等价于
public final ...
public:
void fun(...) final
等价于
public final void fun(...)
class A final{...};
class A final :public ...{};
等价于
final class A{...}
final class A extend ...{...}
(举例?就不举。明白事理远比写一堆没啥意思的测试代码有用)
六.float[10] arr;
首先,c++这样就不行。
报错一长串
java报错:Syntax error on token "10", delete this token
因为java不知道发什么疯把数组也弄成了一个类。联想到java左边的变量名类似于指针,显然c++没有这么玩指针的。因为读到10时为自动寻址,但是此时还没初始化呢,哪来的地址。
所以这两个在我看来其实差不多。
public static void main(String[] args)
{
float[] arr;
arr = new float[]{1,2,3,4,5,6,7};
for (int i = 0; i < arr.length; i++)
{
System.out.println(arr[i]);
}
}
#include
#include
#include
#include
#include
#include
至于数组元素时基本类型和引用类型的区别嘛,差不多就是一般数组和指针数组的区别。由于Java在代码表现上基本不能明显区分引用和实例,从代码上看差距不大,但原理差不多应该就是一般和指针的区别。
七. java 访问控制符
public,protect,private,default(包访问权限);
private :private。
default:包内为public,包外为private。
protected :包内public,包外的子类public,其余private
public:public
注意,不要闲着没事不写关键字,因为c++默认private,java默认同一package内所有成员开放,python在变量名上做文章确定权限。规范化描述不至于把自己写懵。(我自己的习惯)有必要开放就声明开放,没必要就声明不开放,包访问变量应该尽早声明。private与protected要细细思索应不应该给子类开放。
八.子类对父类属性与方法的继承。
参照上文,按照子类与父类在不在一个package内分类就行。
九。组合,重载,复写
类的组合:
class points
{
private int x, y;
points()
{
x = 0;
y = 0;
}
points(int x,int y)
{
this.x = x;
this.y = y;
}
int Getx() {return x;}
int Gety() {return y;}
}
class lines
{
private points l,r;
lines()
{
this.l = new points();
this.r = new points();
}
lines(int a,int b,int c,int d)
{
this.l = new points(a,b);
this.r = new points(c,d);
}
void show()
{
System.out.println("l: ("+l.Getx()+","+l.Gety()+")");
System.out.println("r: ("+r.Getx()+","+r.Gety()+")");
}
}
public class test
{
public static void main(String[] args)
{
lines a = new lines(1,2,3,4);
a.show();
}
}
类套类,只需要调用类的部分方法即可,相当与类指针。
class point
{
private:
int x,y;
public:
point()
{
x = y = 0;
}
point(int x,int y)
{
this->x = x;
this->y = y;
}
int Getx()
{
return this->x;
}
int Gety()
{
return this->y;
}
};
class lines
{
private:
point *l,*r;
public:
lines()
{
l = new point();
r = new point();
}
lines(int a,int b,int c,int d)
{
l = new point(a,b);
r = new point(c,d);
}
void show()
{
cout<<"l:("<Getx()<<","<Gety()<<")"<Getx()<<","<Gety()<<")"<show();
return 0;
}
几乎一样哈。
至于重载与复写,我记得写过了,似乎就在上面。
class points
{
private int x, y;
points()
{
x = 0;
y = 0;
}
points(int x,int y)
{
this.x = x;
this.y = y;
}
int Getx() {return x;}
int Gety() {return y;}
}
class lines
{
private points l,r;
lines()
{
this.l = new points();
this.r = new points();
}
lines(int a,int b,int c,int d)
{
this.l = new points(a,b);
this.r = new points(c,d);
}
void show()
{
System.out.println("l: ("+l.Getx()+","+l.Gety()+")");
System.out.println("r: ("+r.Getx()+","+r.Gety()+")");
}
//void Getx() {System.out.println(l.Getx()+" "+r.Getx());}
//void Gety(){System.out.println(l.Gety()+" "+r.Gety());}
//重载
int Gety(){return Math.abs(r.Gety()-l.Gety());}
int Getx(){return Math.abs(r.Getx()-l.Getx());}
//复写
}
public class test
{
public static void main(String[] args)
{
lines a = new lines(1,2,3,4);
a.show();
System.out.println(a.Getx()+" "+a.Gety());
}
}
十. 子类实例化
(这玩意在一堆乱七八糟得东西里跳了好久,我受不了了啊啊啊啊啊啊!!!!!!!!!)
差不多就是执行初始化->执行子类构造->进入父类初始化->执行父类构造->执行父类剩余->执行子类剩余。
代码就不贴了
十一.互发消息
class A
{
int a = 0;
B b;
boolean c = false;
A()
{
a = 0;
this.b = null;
}
A(B b)
{
a = 0;
this.b = b;
b.a = this;
}
void show()
{
if(c==true)
{
c = false;
return;
}
else if(b!=null)
{
System.out.println("A:hey B!");
if(b.c==true)
{
b.c = false;
return ;
}
c = true;
b.show();
}
else
{
System.out.println("not connected");
}
}
}
class B
{
int b = 0;
A a;
boolean c = false;
B()
{
b = 0;
this.a = null;
}
B(A a)
{
b = 0;
this.a = a;
this.a.b = this;
}
void show()
{
if(c==true)
{
c = false;
return;
}
else if(a!=null)
{
System.out.println("B:hey A!");
if(a.c==true)
{
a.c = false;
return;
}
c = true;
a.show();
}
else
{
System.out.println("not connected");
}
}
}
public class test
{
public static void main(String[] args)
{
//B b = new B();
//A a = new A(b);
A a = new A();
B b = new B(a);
//A a = new A();
//B b = new B();
System.out.println("A first:");
a.show();
System.out.println("B first:");
b.show();
}
}
前俩组输出一致,第三组会报not connected。
十二.组合与继承
组合相当于类中加引用类(指针),相当于friend。继承相当于继承父类的方法,相当于is a。
当类之间有联系但是差别过大时(比如鸟和飞机,除了会飞之外差距蛮大的),两者需要互动(鸟撞飞机,飞机躲避鸟),显然适合使用组合(飞机类里准备鸟的动态数组即可)。但是如果是有明显的子集关系(鸟和兀鹫之间),显然适合于继承的使用。
十三.java多态。
多态:父类的对象变量调用了子类中重写的方法。
abstract class base
{
String name = null;
base()
{
name = null;
}
public abstract void show();
}
class dog extends base
{
String habit = "chase cat";
dog(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
}
class cat extends base
{
String habit = "miao~";
cat(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
}
public class test
{
public static void main(String[] args)
{
base a = new cat("kitty");
base b = new dog("spikes");
a.show();
b.show();
}
}
输出是很显然的。
abstract class base
{
String name = null;
base()
{
name = null;
}
public abstract void show();
}
class dog extends base
{
String habit = "chase cat";
dog(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
public void bomb()
{
System.out.println(name+" is setting the bomb");
}
}
class cat extends base
{
String habit = "miao~";
cat(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
}
public class test
{
public static void main(String[] args)
{
base a = new cat("kitty");
base b = new dog("spikes");
a.show();
b.bomb();
b.show();
}
}
这里仅仅加了一个专属dog的方法bomb,但是此时base引用无法调用子类dog特有的方法,报错显示base类未定义bomb方法。显然,通过调用父类的引用可以定向取用子类中重写父类的方法。但是不能取子类独有的方法。显然在代码层面无法确定父类引用会调用具体的那个方法,仅当运行时根据后面的具体对象进行动态绑定。
((dog)b).bomb();
神奇的是,对b进行向下转型后就可以用了,原因是此时b仅绑定dog实例,且唯一确定。
更神奇的是
#include
#include
#include
#include
#include
#include
一模一样好吧,所以是谁抄谁的呢?
十四.interface
interface Shape
{
abstract void count();
abstract void show();
}
class A implements Shape
{
int a,b,c,ans;
A()
{
a = b = c = 0;
ans = -1;
}
A(int a,int b,int c)
{
this.a = a;this.b = b;this.c = c;
ans = -1;
}
@Override
public void count()
{
ans = a+b+c;
}
@Override
public void show()
{
System.out.print(a+","+b+","+c);
if(ans != -1)
{
System.out.print(","+ans);
}
System.out.println();
}
}
class B implements Shape
{
int a,b,ans;
B()
{
a = b = 0;
ans = -1;
}
B(int a,int b)
{
this.a = a;this.b = b;
ans = -1;
}
@Override
public void count()
{
ans = a+b;
}
@Override
public void show()
{
System.out.print(a+","+b);
if(ans != -1)
{
System.out.print(","+ans);
}
System.out.println();
}
public void change(int c)
{
a = c;
ans = -1;
}
}
public class test
{
public static void main(String[] args)
{
Shape test1 = new A(1,2,3);
Shape test2 = new B(1,2);
B test3 = new B();
test1.count();
test1.show();
test2.count();
test2.show();
//test2.change();
((B)(test2)).change(1);
test3.show();
test3.change(1);
}
}
对于接口,就是一个纯粹的不能再纯粹的虚方法与静态成员及其方法的类,即虚方法与静态成员及其方法的集合。更像是一种啥具体的东西都没有的模板,需要自行继承,复写与填充特殊方法才能成型。在代码上和抽象类很像,甚至连向下转型都一样。
但是,抽象类存在非静态数据成员与方法,接口显然不可以有。实际上抽象类就是一个类,但是可以有自己的方法。同时,接口必须public,抽象类无所谓。抽象类接近is a,接口接近like a。
自不必说,上c++
#include
#include
#include
#include
#include
#include
所以还是那个问题,谁抄谁的呢?
十五.equals
equals方法一般是判断两个引用是不是指向同一个对象,但是经过复写,往往变成比较内容是否一致。
相当于c++在使用指针或者一些大数组等情况时重载=与==与!=。
class A
{
int b =0;
A(int a)
{
this.b = a;
}
boolean equals(A b)
{
if(this.b != b.b)
{
return true;
}
return false;
}
}
public class test
{
public static void main(String[] args)
{
A a1 = new A(1);
A a2 = a1;
A a3 = new A(1);
System.out.println(a1.equals(a2)+" "+a1.equals(a3)+" "+a2.equals(a3));
}
}
应该输出三个false,我故意的。
上c++
c++不能用指针重载,只能用实例的引用以友元函数重载/在类内重载,对比意义不大,不写了。
十六。instanceof
instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。
应用场景,上面的向下转型。
abstract class base
{
String name = null;
base()
{
name = null;
}
public abstract void show();
}
class dog extends base
{
String habit = "chase cat";
dog(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
public void bomb()
{
System.out.println(name+" is setting the bomb");
}
}
class cat extends base
{
String habit = "miao~";
cat(String name)
{
super();
this.name = name;
}
public void show()
{
System.out.println(name+" likes "+habit);
}
}
public class test
{
public static void main(String[] args)
{
base a = new cat("kitty");
base b = new dog("spikes");
a.show();
if(b instanceof dog)
{
dog c = (dog)b;
c.bomb();
}
b.show();
}
}
这样就不会有问题了呢
十七.抽象类与接口的异同
好像写过了呢。
评论列表(0条)