C++基础:虚函数、重载、覆盖、隐藏<转>

转自:http://www.2cto.com/kf/201404/291772.html

虚函数总是跟多态联系在一起,引入虚函数可以使用基类指针对继承类对象进行操作!

虚函数:继承接口(函数名,参数,返回值),但是实现不继承(函数体)

非虚函数:继承接口,也继承实现;

1)虚析构函数(当一个类打算作为基类使用时候,其析构函数必须是虚函数)

构造函数可以为虚函数吗? 不可以,在生成对象的时候,必须向编译器明确指定要生成什么类型的对象,因而不存在虚函数的问题;只有当对象已经存在,我用什么接口去操作它的问题;

例子:

class A
{
public:
A();
virtual~A();
};
class B: public A
{
public: 
B();
~B();
};
int main()
{
A *pA=new B; //调用B的构造函数
delete pA; 
return 0; 
}

这里通过指针A去调用B类的析构函数,但是如果 ~A()不是虚析构函数,就不存在多态,就会去调用A中的析构函数,最后结果可能是B对象中的A成分被析构了,其他 还残留;所以当一个类作为基类时候,其析构函数必须是虚函数,这样防止出现析构不完全的情况;

2)当虚函数出现在构造、析构函数中时(即在构造函数中调用虚函数),函数退化为普通函数。为什么? <>中条款

例子:(转自<>中条例9)

class Transaction

{
public:
Transaction();
virtual void LogTransaction() const = 0;
// ...
};
Transaction::Transaction()
{
// ...
LogTransaction();
}
class BuyTransaction : public Transaction

{
public:
virtual void LogTransaction() const;
// ...
};

这里调用BuyTransaction的构造函数,因为BuyTransaction是继承类所以先调用基类的构造函数,此时派生类独有的那部分还未初始化,<>中这么解释:“这个对象内的BuyTransaction成分还未初始化,最安全的办法是当他不存在,对象在derived成分还未初 始化时该对象不会成为一个derived对象”所以Transaction 的构造函数会调用基类的 LogTransaction() const;而且此处是个纯虚函数,会报错

3)虚函数与覆盖,重载,隐藏

重载首先出现在非继承关系当中,当同一个类中,两个函数的参数不同,名字相同,返回值类型无所谓(函数返回值不作为重载的参考,因为函数调用时候不出现返回值);

注意两个函数可以仅仅因为const与非const的差别来实现重载;

虚函数与覆盖均出现在一个继承体系中,覆盖针对的是普通函数,当父类子类中出现同名(相同返回值,相同参数,相同函数名)要求绝对一致

虚函数在父类子类中,首先在父类中声明该函数为virtual,那么子类可以重新定义该函数的实现,这里主要涉及多态,就是覆盖的情况加上virtual,通过指针或者引用实现多态;

隐藏显得简单粗暴,在继承类中只要出现于父类同名(只要求同样的函数名/变量名,其他返回值,virtual 非virtual不管)的函数,则用对象调用同名函数时候,基类对应的同名函数、变量隐藏,如果要访问其父类的同名成员应该明确使用 基类名::成员来访问;

例子:

class A
{
public:
virtual ~A(){};
void process(int i,char c); //重载,编译期间即可确定该调用哪个函数
char process(double d,int c); //只要函数名相同,返回无所谓,参数不同
void process(int i); 
void process(int i)const; // 此处相当于void process(const A *this,int i);
void process(consttint i); //这里仅仅因为const属性不同即可实现重载
virtual int foo(int, char){...}; 
int foo2(){};
void foo3(int,int ){};
}
class B: public A
{
public:
int foo(int ,char){...}; //虚函数,这里函数接口要严格一致(大部分编译器要求返回值也要一致)
int process(){...}; //隐藏基类函数 
int foo2(){}; // 这里不含虚属性,会覆盖
int foo3(){return 0;}; //会隐藏A类的foo3
}
int main()
{
B b;
A *pA=&b;
pA->foo2(); //这里调用A类的foo2();不涉及多态;
pA->foo(3,‘c‘); //B类foo() 涉及多态
}

总结:

1)覆盖与虚函数是一对兄弟,要求函数的返回值,函数名,参数严格一致,虚函数是覆盖加上virtual的情况;

2) 隐藏是覆盖的推广,覆盖是隐藏的特例,只要求函数名一样,其他不管,在继承体系中,子类的同名函数会将父类的同名函数隐藏;

3)当使用指针时候,指向基类的指针会根据实际对象的类型,选择相应的虚函数执行,如果派生类没有重新定义基类的虚函数,那么依然执行基类的虚函数;

4)当不存在虚函数的情况下,使用基类的指针,不会下降到派生类中去搜索函数;所以virtual属性相当于告诉基类指针:当执行我时,请到相应对象中搜索对应的虚函数;

5)纯虚函数所在的类是抽象类,不能实例化,定义了纯虚函数意味着这个函数只能为父类,其负责定义接口而不负责实现;

6)当使用对象来调用相应的函数时候,主要考虑的是对基类同名函数的隐藏(包括覆盖),而不需要考虑多态;

7)注意构造析构函数中不能调用虚函数,当执行派生类的构造函数时候,先构造的是其基类成分,再执行派生类成分的构造,虚函数此时无意义;

8)c++是个细节非常多,非常复杂的语言;

时间: 2024-10-26 08:01:52

C++基础:虚函数、重载、覆盖、隐藏<转>的相关文章

处理菱形继承问题&&实现一个虚函数的覆盖及调用&&实现以下几个类的成员函数

#include <iostream> #include <string> using namespace std; 1.实现以下几个类的成员函数 2.实现一个虚函数的覆盖及调用 3.处理菱形继承问题. 植物 class Botany { public: //(const string& name) // const char* name Botany(const char* name = "") :_name(name) //构造函数 { //cout

C++ 11 学习3:显示虚函数重载(override)

5.显示虚函数重载 在 C++ 里,在子类中容易意外的重载虚函数.举例来说: struct Base { virtual void some_func(); }; struct Derived : Base { void some_func(); }; Derived::some_func 的真实意图为何? 程序员真的试图重载该虚函数,或这只是意外? 这也可能是 base 的维护者在其中加入了一个与Derived::some_func 同名且拥有相同参数的虚函数. 另一个可能的状况是,当基类中的

C++函数的重载/覆盖/隐藏

一.重载 成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual关键字可有可无. 二.覆盖 覆盖是指派生类函数覆盖基类函数,特征是: (1)范围不同(分别位于派生类与基类): (2)函数名相同: (3)参数相同: (4)基类函数必须有virtual关键字. 三.隐藏 隐藏是指派生类函数屏蔽了与其同名的基类函数,规则如下: (1)如果派生类的函数与基类的函数同名,但是参数不同.此时,不论有没有virtual关键字,基类的函数将被隐藏

重载 覆盖 隐藏

本文转自:http://www.jb51.net/article/54225.htm 本文实例讲述了C++中重载.重写(覆盖)和隐藏的区别,对于C++面向对象程序设计来说是非常重要的概念.具体分析如下: 1.重载:重载从overload翻译过来,是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型. 示例代码如下: ? 1 2 3 4 5 6 7 8 class A{ public:   void test(i

虚函数重载的相关问题

我们首先对下面三个常见的术语进行区分: ①对函数f()进行重载(overload)是表示,在相同的作用域中定义另一个相同的名字(f)的函数,并且这个函数与f()有着不同的参数个数和参数类型.当程序调用函数f()时,编译器将会根据实际提供的参数来选择最匹配的函数. ②对虚函数f()进行覆盖(override)是表示,在派生类中定义一个相同的名字(f)的函数,并且这个函数的参数个数和参数类型与f()是相同的. ③对外层作用域(基类.外部类或者名字空间)中的函数f()进行隐藏(hide)是表示在内层作

c/c++:重载 覆盖 隐藏 overload override overwrite

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

自动设置ip bat文件 虚函数重载

实现软件启动的时候就自动修改ip地址,可以自动调用 重载项目ForcePlate.cpp中的InitInstance()函数,并在该初始化函数中加 ShellExecute(NULL, _T("open"), _T("1.bat"),NULL, m_strEXEPath, SW_SHOW); 1.bat文件:(修改ip) netsh int ip set addr name="本地连接" source=static addr=192.168.2.

[基础] 虚函数

1. 虚函数会导致的结果:直接上个经典例子... class A { public: void a() { cout<<"A.a"<<endl; } virtual void b() { cout<<"A.b"<<endl; } }; class B: public A { public: void a() { cout<<"B.a"<<endl; } void b() {

面向对象基础:函数重载和构造函数

函数的重载 定义: 1.两个或多个函数在同一个类当中: 2.函数名相同: 3.参数列表不同: 例子如下: //类文件A class A{ //以下3个为成员函数 void funA(){ System.out.println("没有参数的funA函数"); } void funA(int i){ //void为空的返回值,funA为函数名,括号内的为参数 System.out.println("带有整型参数的funA函数"); } void funA(int i ,