c++ 继承 虚函数与多态性 重载 覆盖 隐藏
http://blog.csdn.net/lushujun2011/article/details/6827555
2011.9.27
1)
定义一个对象时,就调用了构造函数。如果一个类中没有定义任何构造函数,那么C++编译器就会在某种情况下为该类提供一个默认的不带参数的构造函数。
只要一个类中定义了一个构造函数,不管这个构造函数是不是默认的,C++编译器都不会再提供默认的构造函数,所以,如果定义了自己的构造函数还想调用默认的构造函数的话,必须再重新定义一个默认的构造函数。
2)析构函数不允许带参数,并且一个类中只能有一个虚构函数。
3)在类中定义成员变量时,不能直接给成员变量赋初值!!!
4)函数的重载条件:
1、在同一类中 2、同名函数 3、函数参数类型或者参数的个数不同
注意:返回值不同的同名同参函数不能构成重载
特例:函数重载时,要注意函数带有默认参数这种情况
void output(int a , int b = 5);
void output(int a);
调用时,会产生二义性
5)构造函数顺序:父类->子类
析构函数顺序:子类->父类
6)//在main函数里定义一个子类实例时,子类先调用父类带参数的构造函数,
public:
fish():animal(400,300)
{
cout<<"fish construct"<<endl;
}
7)多重继承:
class B : public C ,public D //B多重继承与C与D,用逗号隔开各个基类便可
继承表说明顺序:C在D之前,构造函数调用先,是按基类表的说明顺序进行初始化的。析构函数则相反。
注意多重继承中的函数二义性问题:
例如:C、D类都有同名函数(形参亦同)output(),B多重继承与C、D,则调用a.output时,则编译不过,出现ambiguous多义性问题
8)
animal *pAn; // 父类指针,父类animal有breathe()函数
fish fh; //子类实例,子类重定义了breathe()函数
pAn = &fh; //父类指针指向子类,编译器把子类隐含地转化做父类animal类型,
fn(pAn); // fn是全局函数,这里调用的是父类animal的breathe()函数
上述父类的breathe()若改为虚函数,则调用的是对象的实际类型,也就是pAn是fish的类型,所以最终调用的是子类的breathe()
9)虚函数与多态性
加virtual关键字的函数为虚函数,它体现了C++中的多态性,在编译的时候,利用迟绑定技术,也就是编译时并不确定调用哪个函数,而是在运行时
才依据对象类型来确定调用哪个函数,C++的多态性用一句话概括:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时就会根据对象的实际类型来确定调用相应的函数。
char *p = new char
new指令分配的对象是在堆中分配的,它本质上是执行了一次malloc()调用,并调用了一次构造函数。由new得到的,只是对象的指针,而不是对象本身。更重要的是由new 得到的对象,原则上需要delete。
基本上可以理解为 定义的时候(int a;)分配了内存。但这样说过于简单,并且很不准确。
对于全局变量,变量事实上是预分配的,在程序调入内存,还没执行之前就分配了。
对于静态变量,也是预分配的,但是真正的生效是在第一次执行定义的时候(注意这句话)。
对于自动变量,每次执行定义指令的时候(int a;)都会分配内存。该内存是在栈中分配的。
还有种寄存器变量,基本和自动变量相同。
/*
函数的覆盖:1)在父类和子类中 2)完全相同的函数(形参亦同)3)都是虚函数
函数的隐藏:1.1)在子类和父类中 2)同名函数(形参同) 3)不是虚函数
2.1)在子类和父类中 2)同名函数(形参不同)
简单的区分:同名函数不是函数的覆盖就是函数的隐藏。
函数的覆盖与虚函数多态性联系在一起,与父类子类有关。
函数的多态性是由虚函数体现的。
函数的重载(同名不同参函数)则是在同一个类之中。
有纯虚函数的基类叫做抽象类,它不能定义一个实例,因为它只为派生类服务,
而继承的派生类必须有其函数的具体实现,否则亦是一个抽象类不能定义实例。
#include <iostream>
#include <stdio.h>
using namespace std;
class Base
{
public:
Base(){
cout << "Base()" << endl;
}
virtual ~Base(){
cout << "~Base()" << endl;
}
virtual void xfn(int i) {cout<<"Base::xfn(int i):" << i <<endl; }
void yfn(float f) {cout<<"Base::yfn(float f):" << f <<endl;}
void zfn() {cout<<"Base::zfn()"<<endl;}
};
class Derived:public Base
{
public:
Derived(){
cout << "Derived()" << endl;
}
~Derived(){
cout << "~Derived()" << endl;
}
void xfn(int i) {cout<<"Derived::xfn(int i):" << i <<endl; }//覆盖了基类的xfn函数
//void yfn(int c) {cout<<"Derived::yfn(int c):" << c <<endl;} //隐藏了基类的yfn函数
void yfn(float c) {cout<<"Derived::yfn(float c):" << c <<endl;} //隐藏了基类的yfn函数
void zfn() {cout<<"Derived::zfn()"<<endl;} //隐藏了基类的zfn函数
};
int main()
{
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
Derived d;//B D
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
Base *pB = &d;//
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
Derived *pD = &d;//
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pB->xfn();//Dx 5
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pD->xfn();//Dx 5
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pB->yfn(3.14f);
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pD->yfn(3.14f);
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pB->zfn();
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
pD->zfn();
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
/*why not the flowlling,do you know?
delete pD;
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
delete pB;
printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__);
*/
;
}
*/
#include <iostream>
using namespace std;
class Base
{
public:
virtual void xfn(int i) {cout<<"Base::xfn(int i)"<<endl; }
void yfn(float f)
{cout<<"Base::yfn(float f)"<<endl;}
void zfn() {cout<<"Base::zfn()"<<endl;}
};
class Derived:public Base
{
public:
void xfn(int i)
{cout<<"Derived::xfn(int i)"<<endl; }//覆盖了基类的xfn函数
void yfn(int c)
{cout<<"Derived::yfn(int c)"<<endl;} //隐藏了基类的yfn函数
void zfn() {cout<<"Derived::zfn()"<<endl;} //隐藏了基类的zfn函数
};
void main()
{
Derived d;
Base *pB = &d;
Derived *pD = &d;
pB->xfn(5);
pD->xfn(5);
pB->yfn(3.14f);
pD->yfn(3.14f);
pB->zfn();
pD->zfn();
//system("pause");
}
c++ 继承 虚函数与多态性 重载 覆盖 隐藏的更多相关文章
- [022]c++虚函数、多态性与虚表
原文出处:http://my.oschina.net/hnuweiwei/blog/280894 目录[-] 多态 虚函数 纯虚函数 虚表 一般继承(无虚函数覆盖) 一般继承(有虚函数覆盖) 多重继承 ...
- 【足迹C++primer】52、,转换和继承虚函数
转换和继承,虚函数 Understanding conversions between base and derived classes is essential to understanding h ...
- C++ 由虚基类 虚继承 虚函数 到 虚函数表
//虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!&q ...
- (C/C++学习)5.C++中的虚继承-虚函数-多态解析
说明:在C++学习的过程中,虚继承-虚函数经常是初学者容易产生误解的两个概念,它们与C++中多态形成的关系,也是很多初学者经常产生困惑的地方,这篇文章将依次分别对三者进行解析,并讲述其之间的联系与不同 ...
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- C++重载覆盖隐藏
写一个程序,各写出重载覆盖 1 // // main.cpp // 2013-7-17作业2 // // Created by 丁小未 on 13-7-17. // Copyright (c) 201 ...
- c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏
C++虚函数表解析(转) ——写的真不错,忍不住转了 http://blog.csdn.net/hairetz/article/details/4137000 浅谈C++多态性 http://bl ...
- 继承自TWinControl的控件不能在设计期间接受子控件,用代码设置子控件却可以(它的自绘是直接改写PaintWindow虚函数,而不是覆盖Paint函数——对TWinControl.WMPaint又有新解了)
这个控件直接继承自TWinControl,因此不是改写Paint;函数,而是直接改写PaintWindow虚函数,它在VCL框架里被直接调用,直接就把自己画好了(不用走给控件Perform(WM_Pa ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
随机推荐
- nginx在linux中安装
下载地址:http://qkxue.net/ 1.2 解压 使用命令:tar zxvf nginx-1.8.1.tar.gz 1.3 切换至解压目录,安装依赖 yum -y install ...
- Spring AOP 系列总括
Spring有两大核心,IOC和AOP.IOC在Java Web项目中无时无刻不在使用,然而AOP用的比较少,尤其是对一些初级程序员,在架构师搭好的框架上开发应用代码,AOP几乎是透明的.然而,项目中 ...
- c#中的23种设计模式
C# 23种设计模式汇总 创建型模式 工厂方法(Factory Method) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节.工厂方法模式的核 ...
- shell中条件判断if中的-z到-d的意思
shell中条件判断if中的-z到-d的意思 [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 ...
- 使用prompt输入一句英文句子和排序方式(升/降),将所有单词按排序方式排序后在网页上输出
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- (转)DoDataExchange执行时机
void CRegisterDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DAT ...
- C开发基础--函数调用栈
发现有一些问题几乎是所有的新人都会遇到,而且也常因为缺乏一些基本的知识而无从下手.函数调用栈的内容就是其中之一.于是花点时间把以前写的内容整理出来. 程序在运行期间,内存中有一块区域,用来实现程序的函 ...
- 老码农教你在 StackOverflow 上谈笑风生
作为一个高大上的码农,你肯定用到过 StackOverflow,必须的.会有人否定这个断言么?那他恐怕不是真正的码农,或者说还没入门.StackOverflow 对于码农的重要性,基本就和诸葛亮对刘备 ...
- [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...
- 程序员必读:Linux内存管理剖析
现在的服务器大部分都是运行在Linux上面的,所以作为一个程序员有必要简单地了解一下系统是如何运行的. 对于内存部分需要知道: 地址映射 内存管理的方式 缺页异常 先来看一些基本的知识,在进程看来,内 ...