c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏

C++虚函数表解析(转) ——写的真不错,忍不住转了  http://blog.csdn.net/hairetz/article/details/4137000

浅谈C++多态性  http://blog.csdn.net/hackbuteer1/article/details/7475622

C++抽象类  http://www.cnblogs.com/dongsheng/p/3343939.html

C++的精髓——虚函数  http://blog.chinaunix.net/uid-26851094-id-3327323.html

C++中的类所占内存空间总结 http://blog.sina.com.cn/s/blog_69c189bf0100mkeu.html

#include <iostream>
#include <stdio.h>
using namespace std;
#include<iostream>
using namespace std;

class A
{
public:
	void foo()
	{
		printf("1\n");
	}
	virtual void fun()
	{
		printf("2\n");
	}
};
class B : public A
{
public:
	void foo()
	{
		printf("3\n");
	}
	void fun()
	{
		printf("4\n");
	}
};
int main(void)
{
	A a;
	B b;
	A *p = &a;
	p->foo();
	p->fun();
	cout<<endl;

	p = &b;//注意p还是A的指针
	p->foo();
	p->fun();
	cout<<endl;

	B *pb = &b;
	pb->foo();
	pb->fun();
    cout<<endl;

	B *ptr = (B *)&a;
	ptr->foo();
	ptr->fun();
	cout<<endl;

	return 0;
}

  

1
2

1
4

3
4

3
2

Process returned 0 (0x0)   execution time : 0.030 s
Press any key to continue.

  

成员函数的重载、覆盖与隐藏
成员函数的重载、覆盖(override)与隐藏很容易混淆,C++程序员必须要搞清楚
概念,否则错误将防不胜防。
8.2.1 重载与覆盖
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。

令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,但是C++的隐藏规则使问题复杂性陡然增加。
这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
上面的程序中:
(1)函数Derived::f(float)覆盖了Base::f(float)。
(2)函数Derived::g(int)隐藏了Base::g(float),而不是重载。
(3)函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。

//小结:1、有virtual才可能发生多态现象
// 2、不发生多态(无virtual)调用就按原类型调用
#include<iostream>
using namespace std;

class Base
{
public:
	virtual void f(float x)
	{
		cout<<"Base::f(float)"<< x <<endl;
	}
	void g(float x)
	{
		cout<<"Base::g(float)"<< x <<endl;
	}
	void h(float x)
	{
		cout<<"Base::h(float)"<< x <<endl;
	}
};
class Derived : public Base
{
public:
	virtual void f(float x)
	{
		cout<<"Derived::f(float)"<< x <<endl;   //多态、覆盖
	}
	void g(int x)
	{
		cout<<"Derived::g(int)"<< x <<endl;     //隐藏
	}
	void h(float x)
	{
		cout<<"Derived::h(float)"<< x <<endl;   //隐藏
	}
};
int main(void)
{
	Derived d;
	Base *pb = &d;
	Derived *pd = &d;
	// Good : behavior depends solely on type of the object
	pb->f(3.14f);   // Derived::f(float) 3.14
	pd->f(3.14f);   // Derived::f(float) 3.14

	// Bad : behavior depends on type of the pointer
	pb->g(3.14f);   // Base::g(float)  3.14
	pd->g(3.14f);   // Derived::g(int) 3 

	// Bad : behavior depends on type of the pointer
	pb->h(3.14f);   // Base::h(float) 3.14
	pd->h(3.14f);   // Derived::h(float) 3.14
	return 0;
}

  

C++纯虚函数
 一、定义
  纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” 
  virtual void funtion()=0 
二、引入原因
   1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。 
   2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。 
  为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
三、相似概念
   1、多态性 
  指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。 
  a、编译时多态性:通过重载函数实现 
  b、运行时多态性:通过虚函数实现。 

  2、虚函数 
  虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override)
  3、抽象类 
  包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

时间: 2024-10-26 02:06:52

c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏的相关文章

虚函数/纯虚函数/抽象类/接口/虚基类

1.多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过父类的指针调用实际子类的成员函数. 在Java中,没有指针,就直接用父类实例化子类对象 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的,多态可以让父类的指针有“多种形态”,这是一种泛型技术. 所谓泛型技术,就是试图使用不变的代码来实现可变的算法 2.虚函数 在基类的类定义中,定义虚函数的一般形式: Virtual 函数返回值类型 虚函数名(形参表){ 函数

C++中的 虚函数 纯虚函数 虚基类(virtual)

前言:需要了解三者的区别,必须要掌握多态的三个必要条件: 继承 重载 父类指针指向子类对象. 虚函数 纯虚函数 虚基类三者区别 1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的. 2.纯虚函数是用来定义接口的,也就是基类中定义一个纯虚函数,基类不用实现,让子类来实现. 3.虚基类是用来在多继承中,比如菱形继承中,如果两个父类继承自同一个类,就只实例化一个父类 ①虚函数第一个是没有使用多态(只用继承)的一般实现方式: class A { public:

C++ 虚函数&amp;纯虚函数&amp;抽象类&amp;接口&amp;虚基类(转)

http://www.cnblogs.com/fly1988happy/archive/2012/09/25/2701237.html 1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过父类的指针调用实际子类的成员函数. 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的. 多态可以让父类的指针有“多种形态”,这是一种泛型技术.(所谓泛型技术,就是试图使用不变的代码来实现可变的算法). 2. 虚函数 2.1

【C/C++学院】0823-静态联合编译与动态联合编译/父类指针子类指针释放/虚函数/纯虚函数概念以及虚析构函数/抽象类与纯虚函数以及应用/虚函数原理/虚函数分层以及异质链表/类模板的概念以及应用

静态联合编译与动态联合编译 #include <iostream> #include <stdlib.h> //散列 void go(int num) { } void go(char *str) { } //class //::在一个类中 class A { public: void go(int num) { } void go(char *str) { } }; void main() { ///auto p = go;编译的阶段,静态联编 void(*p1)(char *s

纯虚函数和抽象类

-------------------siwuxie095 纯虚函数 在 C++ 中,用 纯 字来修饰虚函数,即 纯虚函数 纯虚函数没有函数体,同时在定义时,函数名的后边要加 =0 看如下实例: 纯虚函数在虚函数表中的实现: 如果定义了一个 Shape 类,因为其中有虚函数和纯虚函数, 所以 Shape 类一定有一个虚函数表,当然,也就会有一个 虚函数表指针 在虚函数表中,如果是一个普通虚函数,则对应的函数指针 就是一个有意义的值,如果是一个纯虚函数,则对应的函数 指针的值就是 0 抽象类 纯虚

C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类

类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. 1 //单继承的定义 2 class B:public A 3 { 4 < 派生类新定义成员> 5 }; 6 //多继承的定义 7 class C:public A,private B 8 { 9 < 派生类新定义成员> 10 }; 我们这篇主要说单继承. 派生类共有三种C++类继承方式: 公有继承(public) 基类的公有成员和保护成

c++,纯虚函数与抽象类

1.纯虚函数的定义: (1)虚函数被“初始化”为0的函数.声明纯虚函数的一般形式是virtual 函数类型 函数名(参数表列) =0;(2)纯虚函数没有函数体:(3)最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”; (4)这是一个声明语句,最后必须加分号.(5)不能在当前类中定义 普通的虚函数 class Base { public: int i; void show1(); virtual void show2() ;//普通的虚函数 } 纯虚函数:

C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型,我们如果想通过一个父类指针调用父类.子类中的同名函数的话,这个函数是有要求的: 在父类中,eat函数声明之前必须要加virtual声明eat()函数为虚函数. 一旦某个函数被声明为虚函数,那么所有派生类(子类)中eat()函数都是虚函数. 为了避免你在子类中写错虚函数,在C++11中,你可以在函数

C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数

1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并不是所有代码都是由软件构造师自己写的,有时候需要调用库函数,有时候分给别人写.一名软件构造师可以通过纯虚函数建立接口,然后让程序员填写代码实现接口,而自己主要负责建立抽象类. 2:纯虚函数 纯虚函数是指被标明为不具体实现的虚成员函数,它不具备函数的功能.许多情况下,在基类中不能给虚函数一个有意义的定

虚析构函数与纯虚函数

虚析构函数 通过基类的指针删除派生类对象时,通常情况只调用基类的析构函数 但是,删除一个派生类对象时,应该先调用派生类的析构函数,然后调用基类的析构函数(构造时自顶向下,析构时自底向上) 这种情况会产生内存泄漏,最终导致系统应可用内存不足而崩溃 解决办法 把基类的析构函数声明为virtual,此时派生类的析构函数即使不声明为virtual也为virtual函数 在调用基类的指针删除派生类对象时,会先调用派生类的析构函数,最后调用基类的析构函数 一般方法 如果一个类定义了虚函数,那么析构函数也应该