#include<iostream>
using namespace std;

class A
{
public:
	A(int i=0):size(i)
	{
		cout<<"create class A : size="<<size<<endl;
	}
	virtual  void print()
	{
		cout<<"A:print"<<endl;
	}
	virtual ~A(){
		cout<<"~A()"<<endl;
	}
private:
	int size;
};

class B:public A
{
public:

	B(int i=0):size(i)
	{
		cout<<"create class B : size="<<size<<endl;
	}

	void print()
	{
		cout<<"B:print"<<endl;
	}
	~B(){
		cout<<"~B()"<<endl;
	}
private:
	int size;
};

int main()
{
/*	A *pa =new A[10];               // 创建 A 10次
	delete pa;             // 析构 A 1次
	*/
	A *pa = new B(5);
	pa->print();

	delete pa;
	return 0;
}

 输出:

 


 

若父类A中的输出函数不是虚函数  则输出为:


 

若父类A中析构函数也不是虚函数  则输出为:


与继承有关的基本概念

继承是一个进程,通过继承,一个对象可以获得另一个对象的属性(包括函数),并可向其中加入属于自己的一些特征。作为C++语言的一种重要机制,用 继承的方法可以自动为一个类提供来自另一个类的操作和数据结构,进而使程序设计人员在一个一般的类的基础上很快建立一个新的类,而不必从零开始设计每个 类。

当一个类被其他的类继承时,被继承的类称为基类(可不是鸡肋^_^),又称为父类。

继承其他类属性的类称为派生类,又称为子类。

一般情况下,继承的进程起源于一个基类的定义,基类定义了其所有派生类的公有属性。从本质上讲,基类具有同一类集合中的公共属性,派生类继承了这些属性,并且增加了自己特有的属性。从任何已存在的类继承的实质就是建造新的派生类。

 

继承分为单继承和多继承

 单继承指 派生类只有一个直接基类。  多继承指  派生类有两个或者多个直接基类

继承链:B继承A,C又继承B     

class A
{
    ......
};
class B :public A
{
    ......
};
class C :public B
{
    ......
};

类 A 是 类C的间接基类。当建立类C的对象时,类A 的构造函数最先被调用,接下来被调用的是类B的构造函数,最后是类C的构造函数。析构函数的调用顺序正好相反。

 

  在多继承时,如果存在虚继承和非虚继承,则先顺序调用虚基类, 再顺序调用非虚。


(以下转 http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html)

 

虚继承

 

为何引入虚拟继承?

    虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下:

 

class A

 

class B1:public virtual A;

 

class B2:public virtual A;

 

class D:public B1,public B2;       //    菱形 ◇

 

面试中常考的C++虚拟继承的知识点

第一种情况:         第二种情况:          第三种情况            第四种情况:
class a           class a              class a              class a
{              {                {                 {
    virtual void func();      virtual void func();       virtual void func();        virtual void func();
};              };                  char x;              char x;
class b:public virtual a   class b :public a           };                };
{              {                class b:public virtual a      class b:public a
    virtual void foo();        virtual void foo();     {                 {
};              };                  virtual void foo();        virtual void foo();
                               };                };

如果对这四种情况分别求sizeof(a),  sizeof(b)。结果是什么样的呢?下面是输出结果:(在vc6.0中运行)
第一种:4,12                
第二种:4,4
第三种:8,16       //  存在字节对其。
第四种:8,8

想想这是为什么呢?

因为每个存在虚函数的类都要有一个4字节的指针指向自己的虚函数表,所以每种情况的类a所占的字节数应该是没有什么问题的,那么类b的字节数怎么算呢?看“第一种”和“第三种”情况采用的是虚继承,那么这时候就要有这样的一个指针vptr_b_a,这个指针叫虚类指针,也是四个字节;还要包括类a的字节数,所以类b的字节数就求出来了。而“第二种”和“第四种”情况则不包括vptr_b_a这个指针,

 

 

c++重载、覆盖、隐藏的区别和执行方式


1成员函数被重载的特征
(1)相同的范围(在同一个类中); 
(2)函数名字相同; 
(3)参数不同; 
(4)virtual 关键字可有可无。 
2“覆盖”是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类); 
(2)函数名字相同; 
(3)参数相同; 
(4)基类函数必须有virtual 关键字。 
3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是:

(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 
(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

小结:说白了就是如果派生类和基类的函数名和参数都相同,属于覆盖,这是可以理解的吧,完全一样当然要覆盖了;如果只是函数名相同,参数并不相同,则属于隐藏。

4 三种情况怎么执行:

4.1 重载:看参数。

4.2 隐藏:用什么就调用什么。

4.3 覆盖:调用派生类。