继承中参数传递及调用顺序
一、简单派生类的构造函数传参
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:派生类的构造函数。
复杂派生类的析构函数,只需要编写对新增普通成员的善后处理,而对类对象和基类的善后工作是由类对象和基类的析构函数完成的。析构函数的调用顺序与构造函数相反。
原文地址:http://blog.csdn.net/xaut_zjb/article/details/40949735