继承的构造函数、多重继承、虚继承
程序员文章站
2022-05-14 12:02:48
...
032继承的构造函数
#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;
class A
{
public:
A(int i,int j,int k=7):number01(i),number02(j),number03(k)
{
;
}
A()
{}
public:
int number01;
int number02;
int number03;
};
class B:public A
{
public:
//B(int i,int j, int k):A(i,j,k)
//{
// ;
//}
using A::A;
//继承A的构造函数,using就是让某个名字在当前作用域内可见。遇见这个代码,
//会把基类的每个构造函数都生成一个在子类中。
/*B(构造函数形参列表):A(父类的构造函数形参列表){}
*B(int i,int j, int k):A(i,j,k){}
*如果基类A的构造函数有默认参数的话,那么编译器遇到使用using A::A的时候,
* 就会帮助我们在派生类B中构造出多个构造函数出来
*
*如果基类包含多个构造函数,则在多数情况下,派生类会继承所有这些构造函数,但下面这些情况例外:
* 1.如果派生类中定义的构造函数和基类的构造函数具有相同的参数列表,那么从基类中继承来的构造函数被派生类中定义的覆盖掉。
* (相当于只继承了一部分基类中的构造函数)
* 2.默认构造函数,拷贝构造函数,移动构造函数不会被继承。
* 3.如果类B,只含有using A::A从A继承来的构造函数的话,那么编译器是会合成默认的构造函数。
*/
};
int main(void)
{
B b1(3, 4, 5); //先调用父类的构造函数,再调用子类的构造函数。
B b2;
system("pause");
return 0;
}
/*
*(1)继承的构造函数
* 一个类只调用其直接基类的构造函数。默认构造函数,拷贝构造函数,和移动构造函数是不能被继承。
*
*
*
*/
033多重继承与多层继承
#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;
class GrandFather1
{
public:
int myValueGrand;
public:
GrandFather1(int i):myValueGrand(i)
{}
virtual ~GrandFather1()
{
cout << "GrandFather1的析构函数执行" << endl;
}
void myInfo()
{
cout << "我是GrandFather01" << myValueGrand << endl;
}
};
class GrandFather02
{
public:
int myValueGrand02;
public:
GrandFather02(int i) :myValueGrand02(i)
{}
virtual ~GrandFather02()
{
cout << "GrandFather1的析构函数执行" << endl;
}
void myInfo()
{
cout << "我是GrandFather02" << endl;
}
};
//定义父类
class Father:public GrandFather1
{
public:
int myValueFather;
public:
Father(int i,int k):GrandFather1(i),myValueFather(k)
{
;
}
//Father的析构函数
virtual ~Father()
{
cout << "这是Father类的析构函数" << endl;
}
void myInfo()
{
cout << "我是Father" << endl;
}
};
class Son:public Father
{
public:
int myValueSon;
public:
Son(int i,int j,int k):Father(i,j),myValueSon(k)
{
}
virtual ~Son()
{
cout << "这是son类的洗头函数"<<endl;
}
void myInfo()
{
cout << "我是son" << endl;
}
};
//类Father02同时继承两个GrandFather类
class Father02:public GrandFather1,public GrandFather02
{
public:
int myVlaueFather02;
public:
Father02(int i,int j,int k):GrandFather1(i),GrandFather02(j),myVlaueFather02(k)
{}
virtual ~Father02()
{
cout << "这是类Father02类的析构函数" << endl;
}
void myInfo()
{
cout << "我是Father02,继承自两个Grandfather1,02" << endl;
}
};
class Son02:public Father02
{
public:
int myValueSon02;
public:
Son02(int i,int j,int k,int m):Father02(i,j,k),myValueSon02(m)
{
;
}
};
int main(void)
{
Father02 my_father01(1, 2, 3);//先调用两个GrandFather的构造函数
my_father01.myInfo();//调用Father02类的函数
my_father01.GrandFather02::myInfo();//调用父类的myInfo函数
system("pause");
return 0;
}
/*
*(1)多重继承
*如果从多个父类继承产生子类叫多重继承。
*c继承自B,B继承自A,那么叫多层继承。C-->B-->A
*
*
*(2)继承关系son-->father-->grandfather
*
*son2--Father02-->GranFather1,GrandFather02
*
*
*
*
*/
034派生类构造函数与析构函数顺序
#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;
class A
{
public:
int a;
A(int i):a(i)
{
cout << "A构造函数执行" << endl;
}
virtual ~A()
{
cout << "A析构函数" << endl;
}
};
class B1:public A
{
public:
int b1;
B1(int i,int j):A(i),b1(j)
{
cout << "B1构造函数执行" << endl;
}
virtual ~B1()
{
cout << "B1析构函数" << endl;
}
};
class B2 :public A
{
public:
int b2;
B2(int i, int j) :A(i), b2(j)
{
cout << "B2构造函数执行" << endl;
}
virtual ~B2()
{
cout << "B2析构函数" << endl;
}
};
class C:public B1,public B2 //派生列表
{
public:
int c;
C(int i,int j, int k):B1(i,j),B2(i,j),c(k)
{
cout << "c构造函数执行" << endl;
}
public:
static int static_number;//声明静态变量
public:
virtual ~C()
{
cout << "C析构函数" << endl;
}
};
int C::static_number = 10;//定义变量,分配内存空间,赋予初值
void playObject()
{
C c1(1, 2, 3);
c1.static_number = 12;
C::static_number = 30;
/*析构函数和构造函数调用顺序:
A构造函数执行
B1构造函数执行
A构造函数执行
B2构造函数执行
c构造函数执行
C析构函数
B2析构函数
A析构函数
B1析构函数
A析构函数
请按任意键继续. . .
*
*/
}
int main(void)
{
playObject();
system("pause");
return 0;
}
/*
*(1)静态成员变量 静态成员变量属于类,而不是属于对象
*
*(2)派生类构造函数与析构函数
* 1.构造一个派生类对象将同时构造并初始化所有的基类对象
* 2.派生类的构造函数初始化只初始化它的直接基类。每个类的构造函数都负责初始化它的直接基类。
* 一层一层传递下去。
* 3.派生类构造函数初始化列表将实参值分别传递给它的直接基类。
* 基类的构造顺序和“派生列表”中基类的出现顺序保持一致。
* 4.每个类的析构函数都负责释放自己类分配的内存,子类的析构函数释放子类分配的内存。父类析构函数负责释放父类分配的内存。
*
*显式初始化基类:C(int i,int j, int k):B1(i,j),B2(i,j),c(k)
*隐式初始化基类:当一个基类包含一个不带参数的构造函数,那么初始化的时候可以不出现父类,
* 隐式的使用不带参数的构造函数来初始化。
*
*
*(3)
*
*
*/
035从基类继承构造函数
#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;
class A
{
public:
int a;
A(int i) :a(i)
{
cout << "A构造函数执行" << endl;
}
virtual ~A()
{
cout << "A析构函数" << endl;
}
};
class B1 :public A
{
public:
int b1;
B1(int i, int j) :A(i), b1(j)
{
cout << "B1构造函数执行" << endl;
}
virtual ~B1()
{
cout << "B1析构函数" << endl;
}
};
class B2 :public A
{
public:
int b2;
B2(int i, int j) :A(i), b2(j)
{
cout << "B2构造函数执行" << endl;
}
virtual ~B2()
{
cout << "B2析构函数" << endl;
}
};
class C :public B1, public B2 //派生列表
{
public:
int c;
C(int i, int j, int k) :B1(i, j), B2(i, j), c(k)//自己的版本
{
cout << "c构造函数执行" << endl;
}
//using B1::B1;
//using B2::B2;
public:
static int static_number;//声明静态变量
public:
virtual ~C()
{
cout << "C析构函数" << endl;
}
};
int C::static_number = 10;//定义变量,分配内存空间,赋予初值
void playObject()
{
;
}
int main(void)
{
playObject();
system("pause");
return 0;
}
/*
*(1)从多个父类继承构造函数
* 如果一个类从它的基类中继承了相同的构造函数,这个类必须为该构造函数定义自己的版本。
*
*/
036虚基类与虚继承
#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;
class A
{
public:
int a;
A(int i) :a(i)
{
cout << "A构造函数执行" << endl;
}
A(){}
virtual ~A()
{
cout << "A析构函数" << endl;
}
};
class B1 :virtual public A
{
public:
int b1;
B1(int j) : b1(j)
//B1(int i,int j) :A(i),b1(j)
{
cout << "B1构造函数执行" << endl;
}
virtual ~B1()
{
cout << "B1析构函数" << endl;
}
};
class B2 :virtual public A
{
public:
int b2;
//B2(int i,int j) :A(i),b1(j)
B2(int j) : b2(j)
{
cout << "B2构造函数执行" << endl;
}
virtual ~B2()
{
cout << "B2析构函数" << endl;
}
};
class C :public B1, public B2 //派生列表
{
public:
int c;
//特别注意:这里会调用A类的构造函数,要传递参数
//C(int i, int j, int k) :B1(i, j), B2(i, j), c(k)//自己的版本--不是虚继承
C(int i, int j, int k) : A(i), B1(j), B2(j), c(k)
{
cout << "c构造函数执行" << endl;
}
//using B1::B1;
//using B2::B2;
public:
static int static_number;//声明静态变量
public:
virtual ~C()
{
cout << "C析构函数" << endl;
}
};
int C::static_number = 10;//定义变量,分配内存空间,赋予初值
void playObject()
{
B1*b_point1 = new C(1,2,3); //父类指向子类对象
//A *a_point2 = new C(1, 2, 3);//不能使用爷爷类
//c对象中包含A类的两个副本,解决办法就是使用虚继承
C c2(11, 22, 33);
//c2.a = 12;//C::a不明确
//B1,B2虚继承后
c2.c = 55;
cout << c2.c << endl;
}
int main(void)
{
playObject();
system("pause");
return 0;
}
/*
*(1)类型转换
* 基类指针可以使用子类对象初始化,编译器帮助我们执行隐式的类型转换。因为每个派生类都包含一个基类对象部分。
* 基类引用或者指针可以绑定到基类对象这部分上来的。
*(2)派生列表中,同一个基类只能出现一次,但是以下两种情况除外:
* 1.派生类可以通过它的两个直接基类分别继承同一个简介基类(爷爷类是一个)
* 2.直接继承一个基类,然后通过另一个基类间接继承该类
*(3)虚基类 virtual base class 虚继承
* 虚基类的特点:无论这个类在继承中出现多次,派生类只会包含一个共享的虚基类内容。
*
* 虚继承只影响从父类中派生出来的孙子类,对本身父类没有印象。
* 每个父类都要虚继承爷爷类。
* 爷爷类A-->父类B1,B2(这里进行虚继承),--->孙子类 --virtual和public的位置可以互换
*(4) C(int i, int j, int k) : A(i), B1(j), B2(j), c(k)
* 1.当不进行虚继承的时候,B1,B2都会初始化爷爷A类,更改为虚继承之后,孙子C类就需要单独来初始化爷爷类
* 因为父类B不确定哪一个类进行初始化。
* 相应的父类构造函数也不需要初始化爷爷类对象。
* 2.初始化顺序发生改变。先初始化虚基类部分(A),然后按照派生列表的顺序来初始化其他类。
* 3.多个虚基类,哪个先初始化?
* 按照派生列表中虚基类出现的顺序构造
*总结
* 1.小心虚继承的二义性问题
* 2.在简单情况下,并且不容易出现二义性,实在必要才使用多继承。不建议使用多继承。
*
*
* 2019年11月23日19:52:23
* Sunrise于东北电力大学第二教学楼1121实验室
*
*/
上一篇: 构造函数调用虚函数的问题
下一篇: linux系统下定时执行php脚本的方法