向基类构造函数传递参数

时间:2022-12-17 19:27:41

引言:

继承固然为我们节省了不少的时间和工序,但是由于子类是由基类派生出来的,因此我们在创建派生类的对象时,仍然需要对基类进行初始化。原因也不难理解,因为子类将基类的所有成员都继承了过去,所以被继承的成员也会出现在子类里,那么我们在构造一个子类的对象时,就会难免调用基类的构造函数。

在创建派生类的构造函数时,有两种方法可以对数据进行初始化。

第一种:在派生类中创建一个构造函数,然后初始化所以数据(从基类那里继承来的数据和子类的数据)。这种方法显然是多余的,因为基类已经有了恰当的构造函数,况且在派生类中对基类进行初始化的这种做法也不可取。

第二种:在派生类中创建一个构造函数,然后用该构造函数调用基类的构造函数并且向构造函数传递初始值。

显然,第二种方法的效率要高一些,并且出错的几率要小些。

下面我们用实例进行一下说明:

首先采用第一种方式,也就是在子类的构造函数中为子类对象的所以数据成员赋值。

Code 1:

#include<iostream>

#include<string>

using namespace std;

class Father

{

public:

       Father()

       {

              cout<<"?构造基类对象\n";

       }

       ~Father()

       {

              cout<<"析构基类对象\n";

       }

       void print()

       {

              cout<<name<<"身高为:"<<height<<"kg"<<endl;

       }

protected:

       string name;

       int height;

};

class Son:public Father

{

public:

       Son(string a,int i,int j)//第一个参数给姓名赋值,第二个参数给身高赋值,第三个参数给体重赋值,它们均为子类的构造函数所创建的子类对象的数据成员

       {

              name=a;//继承自父类对象的数据成员             

height=i;//继承自父类对象的数据成员

              weight=j;//子类中添加的数据成员

              cout<<"构造子类对象\n";

       }

       ~Son()

       {

              cout<<"析构子类对象 \n";

       }

       void print1()

       {

              print();//调用子类继承自父类的print函数,即子类的print函数,只不过该print函数是继承自父类

              cout<<name<<"体重为::"<<weight<<"kg"<<endl;

       }

protected:

       int weight;

};

int main()

{

       Son Mary("Mary",160,50);

       Mary.print1();

       return 0;

}

该方法的弊端:在调用父类的构造函数时对与创建子类对象没有什么左右,该父类构造函数的调用不关没有用,还增加了系统的开销。一个高质量的代码是不应当产生或者应该尽量避免产生多余的系统开销的。我们通过方法2来解决这个问题。相关的程序代码如下:

Code 2:

#include<iostream>

#include<string>

using namespace std;

class Father

{

public:

       Father(string n,int h)

       {

              name=n;

              height=h;

              cout<<"?构造基类对象\n";

       }

       ~Father()

       {

              cout<<"?析构带两个参数的基类对象\n";

       }

       void print()

       {

              cout<<name<<"身高为:"<<height<<"kg"<<endl;

       }

protected:

       string name;

       int height;

};

class Son:public Father

{

public:

       Son(string a,int i,int j):Father(a,i)//在子类的构造函数中显示地调用父类的带两个参数的构造函数,同时为它传递两个参数

       {

              weight=j;

              cout<<"?构造子类对象\n";

       }

       ~Son()

       {

              cout<<"?析构子类对象\n";

}

       void print1()

       {

              print();

              cout<<name<<"体重为::"<<weight<<"cm"<<endl;

       }

protected:

       int weight;

};

int main()

{

       Son Mary("Mary",160,50);

       Mary.print1();

cout<<”程序结束”;

       return 0;

}

这样我们就在构造子类对象之前,调用父类的带两个参数的构造函数完成了对父类的两个成员name和height的赋值。这样子类对象在继承了这两个成员之后就不再对这两个成员进行赋值了,而只需要对子类中的数据成员(weight)进行赋值。这样父类的构造函数就充分被利用起来了。另外,显示地调用父类的构造函数可使代码的可读性增强,别人在度这段代码的时候,一下子就可以明白子类构造函数中前两个参数的值是通过父类的构造函数赋给了父类中定义的两个成员,而不是赋给了子类中定义的成员,子类仅仅是继承了父类的两个成员。这种将父类成员和子类成员分开赋值的方法,可以使代码的可读性大大增强,同时减少了出错的可能。