关于C++与Java中虚函数问题的读书笔记

          之前一直用C++编程,对虚函数还是一些较为肤浅的理解。可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题。

Java中的虚函数

          以下是段别人的代码,输入结果竟是Base,这让一直以来用C/C++的我有些莫不着头脑,不是Java里对象是引用吗?C/C++中通过指向基类的指针或引用来指向派生类,那么对于虚函数来说通过基类指针使用的是指向的派生类。但在Java中没有keyword标明虚函数,此时就不是非常明确究竟调用的谁。

class base
{
    private void print()
    {
         System.out.println("base");
    }
    public void doprint()
    {
         print();
    }
}

class derive extends base
{
    private void print()
    {
         System.out.println("derive");
    }
}

class testVirtual
{
    public static void main(String args[])
    {
         base b = new derive();
         b.doprint();
    }



}

          而以下这段Java输出的是derived,注意函数以及訪问权限的变化。

class base
{
    public void print()
    {
         System.out.println("base");
    }
    public void doprint()
    {
         print();
    }
}

class derive extends base
{
    public void print()
    {
         System.out.println("derive");
    }
}

class testVirtual
{
    public static void main(String args[])
    {
         base b = new derive();
         b.print();
    }
}

         大牛甲如是说:“java里的protected,public,包訪问级别的函数都是虚函数。”也有大牛乙如是说:“java里的都是虚函数。”我的解读是这二位大牛的话肯定都对,private级别的函数也能够说是虚函数,仅仅只是基类的引用无法直接訪问派生类的private级别的函数罢了,仅仅能訪问自己的。

      于是能够断定以下这段就是输出derive了。没错,就是这样。

class base {
 private void print() {
  System.out.println("base");
 }

 public void doprint() {
  print();
 }
}

class derive extends base {
 private void print() {
  System.out.println("derive");
 }
 public void doprint() {
  print();
 }
}

class testVirtual {
 public static void main(String args[]) {
  base b = new derive();
  b.doprint();
 }
}


C++中的虚函数

       以下这段C++代码输出的是drived,通过基类的指针或引用指向派生类或基类,然后调用二者共同拥有都有的作为虚函数的函数,此时调用的是指针所指向的类(能够是基类也能够是派生类,关键看此时基类的指针或引用指向的是派生类还是基类)。注意仅仅有基类的指针或引用才干实现虚函数有关多态的问题,其它类型在C++中仅仅调用自己的函数。

#include<iostream>
using namespace std;

class base
{
private:
 virtual void print()
 {
  printf("base
");
 } 
public:
 void doprint()
 {
  print();
 }
 virtual ~base(){}
};

class derived : public base
{
 virtual void print()
 {
  printf("derived
");
 }
};

int main(int argc, char* argv[])
{
 derived d;
 base& b = d;
 b.doprint();
 return 0;
}
//也是derived
#include<iostream>
using namespace std;

class base
{
private:
	virtual void print()
	{
		printf("base
");
	}	
public:
	void doprint()
	{
		print();
	}
	virtual ~base(){}
};

class derived : public base
{
	private:
	virtual void print()
	{
		printf("derived
");
	}
	public:
	void doprint()
	{
		print();
	}
};

int main(int argc, char* argv[])
{
	derived d;
	base& b = d;
	b.doprint();
	return 0;
}
//输出的是base
#include<iostream>
using namespace std;

class base
{
private:
	virtual void print()
	{
		printf("base
");
	}	
public:
	void doprint()
	{
		print();
	}
	virtual ~base(){}
};

class derived : public base
{
	private:
	virtual void print()
	{
		printf("derived
");
	}
	public:
	void doprint()
	{
		print();
	}
};

int main(int argc, char* argv[])
{
	derived d;
	base b = d;
	b.doprint();
	return 0;
}


      以下这段输出的就是base了,由于不是虚函数,通过基类的指针或引用调用的就是基类的函数。

#include<iostream>
using namespace std;

class base
{
public:
	void print()
	{
		printf("base
");
	}	
	virtual ~base(){}
};

class derived : public base
{
	public:
	void print()
	{
		printf("derived
");
	}
};

int main(int argc, char* argv[])
{
	derived d;
	base& b = d;
	b.print();
	return 0;
}

         以下C++代码输出的是derived,这就是同名覆盖原则,派生类覆盖积累的同名函数。

#include<iostream>
using namespace std;

class base
{
public:
	void print()
	{
		printf("base
");
	}	
	virtual ~base(){}
};

class derived : public base
{
	public:
	void print()
	{
		printf("derived
");
	}
};

int main(int argc, char* argv[])
{
	derived d;
	base& b = d;
	d.print();
	return 0;
}


总结对照
C++                     Java
虚函数     --------    普通函数
纯虚函数   --------    抽象函数
抽象类     --------    抽象类
虚基类     --------    接口     
      关于虚函数的实现机制,涉及虚函数表等,兴许博客补上。因为理论知识不足,难以上升到详细底层实现,望理解!