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

1.所谓简单派生类,就是指派生类中不包含基类的内嵌对象的派生类。

2.一般来说,这样的派生类的构造函数的形式是:

 student( int i, string nam, int sid) : person( i, nam) { stuid = sid; }

  person(是基类的初始化列表

3.构造函数的初始化列表的使用

  3.1所有的构造函数都可以拿参数的初始化表来构造完全属于自己的数据成员(其实本质上参数的初始化列表里只能出现两种东西,下文会总结),比如:

 #include <iostream>
using namespace std;
class A
{
public:
A(int a) :dataA(a){ cout << "调用A的构造函数" << endl; }
private:
int dataA;
};
void main()
{
A a();
}

  

  3.2但是一定要注意派生类在构造基类成分的时候不能直接使用参数的初始化表(其实本质上参数的初始化列表里只能出现两种东西,下文总结)

    B(int b, int a) :dataA(a), dataB(b){ cout << "调用B的构造函数" << endl; }//错误!!

   这里一定要再次补充一点,之所以这里不能使用dataA(a)作为初始化的语句,而一定要强制使用基类的构造函数,其原因是基类的数据成员dataA在派生类里是无法访问的,而要使派生类中的基类成分赋值,就必须使用基类的构造函数。但是,倘若基类中的成员dataA我不使用private类型,我使用protected类型的数据,这样B公有继承A之后,dataA就仍然是protected类型,就可以在B类型中访问了,但是这个时候访问dataA的方式任然不能在初始化列表里进行。

  捣弄dataA的过程中也是要遵守一些规则的:

#include <iostream>
using namespace std;
class A
{
protected:
int dataA;
int dataA2;
public:
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
int dataB;
public:
B(int a, int b) : dataB(b){ dataA = a; }
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl<< endl;
B b(, );
}

  上边的代码编译的时候会报错,在执行 B(int a, int b) : dataB(b){ dataA = a; }这句代码的时候,初始化列表中一定会调用一个基类A的无参构造函数,但是A类中没有定义无参构造函数,所以这句话一定会报错!

  把代码改成这样:(加上第9句)

 #include <iostream>
using namespace std;
class A
{
protected:
int dataA;
int dataA2;
public:
A(){}
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
int dataB;
public:
B(int a, int b) : dataB(b){ dataA = a; }
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl<< endl;
B b(, );
} 

  上边这句话写成这样就又错了:

B(int a, int b) : dataB(b) ,dataA(a){}//错误!!!

  

  很明显,放在初始化列表里的数据类型只能是(1)该类新增的数据成员(不包括基类的成员)(2)基类的构造函数

  然后,再看看改了的代码:

 #include <iostream>
using namespace std;
class A
{
private:
int dataA4;
protected:
int dataA;
int dataA2;
public:
A(){}
int dataA3;
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
private:
int dataB;
protected:
int dataB2;
public:
B(int a, int b, int c,int d,int e,int f) : dataA4(f),dataA3(e),dataA2(d),dataB(b), dataB2(c){ dataA = a; }//错误代码!!
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl << endl;
B b(, , ,,,);
}

  这里的错误有两个,一个是dataA4是基类的私有成员,无法在B中访问,自然不能写在B的初始化列表里;二是dataA3和dataA2虽然在B中访问权限一个是公有,一个是保护,但是他们并不是B的新增数据成员,所以不能在B的初始化列表里出现,但是可以在B的构造函数的函数体里出现!

  所以,把代码改成这样:

    B(int a, int b, int c, int d, int e) :dataB(b), dataB2(c){ dataA = a; dataA2 = d; dataA3 = e; }

   3.3也不能把其他语句如输出语句写出来:

B(int b, int a) :A(a), dataB(b), cout << "调用B的构造函数" << endl{}//错误!!!!

  

  3.4同时调用基类的构造函数数据成员的初始化表是可以的

 #include <iostream>
using namespace std;
class A
{
public:
A(int a) :dataA(a){ cout << "调用A的构造函数" << endl; }
private:
int dataA;
};
class B:public A
{
int dataB;
public:
B(int b, int a) :A(a), dataB(b) { cout << "调用B的构造函数" << endl; }
};
void main()
{
B b(, );
}
     B(int b, int a) :A(a), dataB(b) { cout << "调用B的构造函数" << endl; }

  这一行代码就是这样,dataB(b)提到初始化列表中去写,A(a)是基类的构造函数,这样显得很简洁。

  而且代码的调用顺序和dataB(b)的位置无关,都是先初始化A(a),然后初始化dataB,最后执行函数体。

  

  3.5然而这样写成这样不可以的:

   B(int b, int a) :A(a) {dataB(b);cout << "调用B的构造函数" << endl; }//错误!!

  函数体中要用dataB=b;

B(int b, int a) :A(a), dataB = b { cout << "调用B的构造函数" << endl; }//错误!!

  外边要用dataB(b); 

 这样才是正确的写法:

B(int b, int a) :A(a){ dataB=b; cout << "调用B的构造函数" << endl; }

    

【C++学习之路】派生类的构造函数(一)的更多相关文章

  1. 【C++学习之路】派生类的构造函数(三)

    三.多层继承的派生类 1.多层继承的派生类只需在构造函数的初始化列表中写出直接基类的构造函数即可 class student { public: student(int n, string nam) ...

  2. C++学习之路—继承与派生(二):派生类的构造函数与析构函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 由于基类的构造函数和析构函数是不能被继承的,所以 ...

  3. C++学习17派生类的构造函数

    基类的构造函数不能被继承,在声明派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数来完成.所以在设计派生类的构造函数时,不仅要考虑派生类新增的成员变量,还要考虑基类的成员变量,要让它们都 ...

  4. C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序

    基类和派生类:构造函数和析构函数的执行顺序 在Visual Studio中,新建控制台工程,构造类如下: #include<iostream> using namespace std; c ...

  5. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

  6. 【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符

    学习资料 • 派生类的赋值运算符/赋值构造函数也必须处理它的基类成员的赋值 • C++ 基类构造函数带参数的继承方式及派生类的初始化 定义拷贝构造函数 [注意]对派生类进行拷贝构造时,如果想让基类的成 ...

  7. 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)

    [源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...

  8. C++:派生类的构造函数和析构函数

    4.2 派生类的构造函数和析构函数4.2.1 派生类构造函数和析构函数的执行顺序 通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数:当撤销派生类对象时,则先执行派生类 ...

  9. 【C++继承与派生之二】有子对象的派生类的构造函数

    这是我今天看书刚刚看到的,觉着以前对这一块内容了解不多,所以整理一下分享给大家.首先要介绍一下子对象的概念.类的数据成员不仅可以是int.char这样的基本类型,也可以是类对象,如可以包含这样的数据成 ...

随机推荐

  1. Xcode7调试-b

    Xcode7中苹果为我们增加了两个重要的debug相关功能.了解之后觉得非常实用,介绍给大家. 1.Address Sanitizer: 妈妈再也不用担心 EXC_BAD_ACCESS? EXC_BA ...

  2. 自然语言处理(5)之Levenshtein最小编辑距离算法

    自然语言处理(5)之Levenshtein最小编辑距离算法 题记:之前在公司使用Levenshtein最小编辑距离算法来实现相似车牌的计算的特性开发,正好本节来总结下Levenshtein最小编辑距离 ...

  3. ExtJs5_继承自定义一个控件

    Extjs的开发都可以遵循OOP的原则,其对类的封装也很完善了.自定义一个控件最简单的办法就是继承一个已有的控件.根据上一节的需要,我做了一个Button的子类.首先根据目录结构,在app目录下建立一 ...

  4. SIM卡读卡器的研究与设计

    SIM卡(Subscriber Identity Module).即用户识别模块,是一张符合GSM规范的"智慧卡".SIM卡可以插入任何一部符合GSM规范的移动电话中," ...

  5. 调试makefile—subst函数

    操作系统:ubuntu10.04 Makefile里的subst用法是$(subst FROM,TO,TEXT),即将TEXT中的东西从FROM变为TO Makefile中的字符串处理函数格式:    ...

  6. C++类型转换[转]

    转自 http://www.cnblogs.com/goodhacker/archive/2011/07/20/2111996.html C风格的强制类型转换(Type Cast)很简单,不管什么类型 ...

  7. Gmail邮件功能那么强大,GMail被封,在国内怎么用gmail收邮件?

    IT圈子里最热门的话题一定是:gmail被封,该怎么办?gmail由于强大的邮件功能,ITer一定是人手一个or多个,之前想要收发gmail使用imap或SMTP方式是可以在国内正常使用的,目前ima ...

  8. 点击按钮弹出div,留用

    <input type="button" onclick="document.getElementById('div').style.display=(docume ...

  9. 通过linux ssh远程登录另一台Linux,无需密码,用证书验证

    1.首先登入一台linux服务器,此台做为母机(即登入其他linux系统用这台做为入口):执行一行命令生成key文件:ssh-keygen -t rsa 2.在母机上,进入/roo/.ssh目录,找到 ...

  10. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...