• 继承中參数传递及调用顺序


    继承中參数传递及调用顺序

    一、简单派生类的构造函数传參

    C++语言的继承特性,指子类能够继承父类的属性和行为,并能够又一次定义或加入新的属性和行为。

    父类中为private型的属性和行为尽管被继承,可是子类中仍不能訪问。在继承机制下。构造函数是不能被继承的,所以基类构造函数的參数要由子类构造函数传。

    单一继承的子类构造函数的声明(.h中)形式为:

    派生类构造函数名(參数总表) ();

    单一继承的子类构造函数的定义(.cpp中)形式为:

    派生类名::派生类构造函数名(參数总表) : 基类构造函数名 (參数名表)

    {

    派生类新增成员的初始化语句;

    };  

    定义派生类的构造函数时,在构造函数的參数总表中包含基类构造函数所需的參数和派生类新增的数据成员初始化所需的參数。冒号后面基类构造函数名 (參数名表),表示要调用基类的构造函数。

    #include "stdafx.h"
    
    #include <iostream>    
    #include <string>    
    using namespace std;    
    
    class parent
    {
    public:
    	parent(int a,int b)  //基类构造函数,须要传入两个參数
    	{ 
    		//基类的初始化
    		this->a = a;
    		this->b = b;
    	}
    public:	
    	int a,b;
    };
    
    class child:public parent
    {
    public:
    	child(int a,int b,int c); //子类构造函数含參数总表(全部參数)
    	void ShowTest()
    	{
    		cout<<"a = "<<a<<endl;
    		cout<<"b = "<<b<<endl;
    		cout<<"c = "<<c<<endl;
    	}
    
    public:
    	int c;
    };
    
    //子类构造函数的定义,利用初始化表括进行參数初始化
    child::child(int a,int b,int c):parent(a,b)
    {
    	//子类參数的初始化
    	this->c = c;
    }
    
    
    void test()
    {
    	child t1(1,2,3);
    	t1.ShowTest();
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test();
    	system("pause");
    	return 0;
    }
    測试结果:


    二、复杂派生类的构造函数和析构函数

    一个派生类中新添加的成员能够是简单的数据成员。也能够是类对象。派生类须要初始化的数据有三部分:继承的成员、新增类对象的成员和新增普通成员。

    这样的复杂派生类的构造函数定义例如以下:

    派生类名::派生类构造函数名(总參数表) 

       :基类构造函数名1 (參数表1),

        基类构造函数名2 (參数表2),    ……

        子对象名1(參数表n),

         子对象名2(数表n+1)    ……

    {

            派生类新增普通数据成员的初始化。

    }

    // test.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <iostream>    
    #include <string>    
    using namespace std;    
    
    class A
    {
    public:
    	A(){}
    	A(int i){a = i;}
    	~A(){}
    	void Print(){
    		cout<<"a = "<<a<<endl; 
    	}
    	int Geta(){ return a;}
    private:
    	int a;
    };
    
    class B
    {
    public:
    	B(){}
    	B(int i){b = i;}
    	~B(){}
    	void Print(){
    		cout<<"b = "<<b<<endl; 
    	}
    	int Getb(){ return b;}
    private:
    	int b;
    };
    
    class C:public A
    {
    public:
    	C(void){}
    	C(int i,int j,int k):A(i),b1(j)
    	{
    		c = k;
    		
    	}
    
    	~C(void){}
    	void Print(){
    		cout<<"a = "<<Geta()<<endl; 
    		cout<<"b = "<<b1.Getb()<<endl;
    		cout<<"c = "<<c<<endl; 
    	}
    private:
    	int c;
    	B b1;
    };
    
    void test()
    {
    	C c1(1,2,3);
    	c1.Print();
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test();
    	system("pause");
    	return 0;
    }

    測试结果:


    注:在vs2010编译环境下,若将声明处C(void){}改为C(void);则会出现编译错误:

    1).obj : error LNK2019: 无法解析的外部符号 "public: __thiscall C::C(void)" (?

    ?0C@@QAE@XZ)。该符号在函数 "void __cdecl test(void)" (?

    test@@YAXXZ) 中被引用

    2)fatal error LNK1120: 1 个无法解析的外部命令

    原因是另外一种方法默认仅仅声明了构造函数,并没有实现。第一种则为函数定义实现方式,尽管“;”与{}作用相似,但此处不一样!

    !!


    知识点总结:

    派生类构造函数的调用顺序例如以下:

    Step1:基类构造函数。

    按它们在派生类定义中的先后顺序,依次调用。

    Step2:内嵌对象的构造函数。

    按它们在派生类定义中的先后顺序,依次调用。

    Step3:派生类的构造函数。

       复杂派生类的析构函数,仅仅须要编写对新增普通成员的善后处理,而对类对象和基类的善后工作是由类对象和基类的析构函数完毕的。析构函数的调用顺序与构造函数相反。




  • 相关阅读:
    随机数、无重复、冒泡排序
    今天是星期几
    Button
    2012/8/5为应用指定多个配置文件
    2012/8/4解决JSP显示中文乱码
    2012/8/4 struts2学习笔记
    2012/8/4Action中result的各种转发类型
    2012/8/4为Action属性注入值
    2012/8/3SVN小入门
    2012/8/3 Extjs使用TabPanel时需要注意的问题
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5255418.html
Copyright © 2020-2023  润新知