C++继承运行顺序
构造顺序:
/*************************************************************************
> File Name: test2.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sat Oct 28 14:43:07 2023
************************************************************************/
#include <iostream>
using namespace std;
class ATTR_BASE{
public:
ATTR_BASE(string str) : str(str) {
cout << "ATTR_BASE = " << str << endl;
}
private:
string str;
};
class ATTR1 : public ATTR_BASE {
public:
ATTR1(string str = "none") : ATTR_BASE(str) {}
};
class ATTR2 : public ATTR_BASE {
public:
ATTR2(string str = "none") : ATTR_BASE(str) {}
};
class BASE{
public:
BASE() : attr1("ATTR1"), attr2("ATTR2") {
cout << "class BASE" << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
class A : public BASE {
public:
A() : attr1("ATTR1 in BASE"), attr2("ATTR2 in BASE") {
cout << "class A" << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
return 0;
}
我们来运行一下看看是这么构造的
可以发现调用顺序是这样的:先构造父类,在按照定义的成员属性的顺序来进行构造。至于为什么会这样呢?因为成员属性的构造可能是建立在父类的基础上在进行构造的,而成员属性也是一个道理,后定义的成员属性,可能是在先定义成员属性的基础的上进行构造的。
析构顺序:
/*************************************************************************
> File Name: test2.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sat Oct 28 14:43:07 2023
************************************************************************/
#include <iostream>
using namespace std;
class ATTR_BASE{
public:
ATTR_BASE(string str) : str(str) {
cout << "ATTR_BASE = " << str << endl;
}
~ATTR_BASE() {
cout << "~ATTR_BASE = " << str << endl;
}
private:
string str;
};
class ATTR1 : public ATTR_BASE {
public:
ATTR1(string str = "none") : ATTR_BASE(str) {}
};
class ATTR2 : public ATTR_BASE {
public:
ATTR2(string str = "none") : ATTR_BASE(str) {}
};
class BASE{
public:
BASE() : attr1("ATTR1"), attr2("ATTR2") {
cout << "class BASE" << endl;
}
~BASE() {
cout << "~BASE = " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
class A : public BASE {
public:
A() : attr1("ATTR1 in BASE"), attr2("ATTR2 in BASE") {
cout << "class A" << endl;
}
~A() {
cout << "~A() " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
cout << "*************************" << endl;
return 0;
}
运行一下,看看顺序:
可以发现,和构造顺序是完全相反的,这个原因是因为后构造的成员属性,可能在有先构造成员属性的基础上才能正常析构。
拷贝顺序:
/*************************************************************************
> File Name: test2.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sat Oct 28 14:43:07 2023
************************************************************************/
#include <iostream>
using namespace std;
class ATTR_BASE{
public:
ATTR_BASE(string str) : str(str) {
cout << "ATTR_BASE = " << str << endl;
}
ATTR_BASE(const ATTR_BASE &a) : str(a.str) {
cout << "default copy construct : " << str << endl;
}
~ATTR_BASE() {
cout << "~ATTR_BASE = " << str << endl;
}
private:
string str;
};
class ATTR1 : public ATTR_BASE {
public:
ATTR1(string str = "none") : ATTR_BASE(str) {}
};
class ATTR2 : public ATTR_BASE {
public:
ATTR2(string str = "none") : ATTR_BASE(str) {}
};
class BASE{
public:
BASE() : attr1("ATTR1"), attr2("ATTR2") {
cout << "class BASE" << endl;
}
BASE(const BASE &a) {
cout << "BASE" << endl;
}
~BASE() {
cout << "~BASE = " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
class A : public BASE {
public:
A() : attr1("ATTR1 in BASE"), attr2("ATTR2 in BASE") {
cout << "class A" << endl;
}
~A() {
cout << "~A() " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
cout << "********************" << endl;
A b(a);
cout << "********************" << endl;
return 0;
}
我们来看看这个的运行结果
我们A
类调用的是系统默认的拷贝构造,这时它会按照构造的顺序依次进行拷贝构造,我们发现这里BASE
类调用的是构造函数,而非拷贝构造,这是因为我们自己手动写了一个拷贝构造,所以会调用我们自己写的这个拷贝构造,而在我们自己写的拷贝构造函数里,我们并没有进行赋值操作,所以它会自动调用构造函数。
我们给拷贝构造写完整在看看运行结果
/*************************************************************************
> File Name: test2.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sat Oct 28 14:43:07 2023
************************************************************************/
#include <iostream>
using namespace std;
class ATTR_BASE{
public:
ATTR_BASE(string str) : str(str) {
cout << "ATTR_BASE = " << str << endl;
}
ATTR_BASE(const ATTR_BASE &a) : str(a.str) {
cout << "default copy construct : " << str << endl;
}
~ATTR_BASE() {
cout << "~ATTR_BASE = " << str << endl;
}
private:
string str;
};
class ATTR1 : public ATTR_BASE {
public:
ATTR1(string str = "none") : ATTR_BASE(str) {}
};
class ATTR2 : public ATTR_BASE {
public:
ATTR2(string str = "none") : ATTR_BASE(str) {}
};
class BASE{
public:
BASE() : attr1("ATTR1"), attr2("ATTR2") {
cout << "class BASE" << endl;
}
BASE(const BASE &a) : attr1(a.attr1), attr2(a.attr2) {
cout << "BASE" << endl;
}
~BASE() {
cout << "~BASE = " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
class A : public BASE {
public:
A() : attr1("ATTR1 in BASE"), attr2("ATTR2 in BASE") {
cout << "class A" << endl;
}
~A() {
cout << "~A() " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
cout << "********************" << endl;
A b(a);
cout << "********************" << endl;
return 0;
}
运行结果
我们把拷贝构造补充完整之后,我们的运行结果就符合我们心里预期了。
赋值顺序:
/*************************************************************************
> File Name: test2.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sat Oct 28 14:43:07 2023
************************************************************************/
#include <iostream>
using namespace std;
class ATTR_BASE{
public:
ATTR_BASE(string str) : str(str) {
cout << "ATTR_BASE = " << str << endl;
}
ATTR_BASE(const ATTR_BASE &a) : str(a.str) {
cout << "default copy construct : " << str << endl;
}
ATTR_BASE &operator=(const ATTR_BASE &a) {
str = a.str;
cout << "operator = " << str << endl;
return *this;
}
~ATTR_BASE() {
cout << "~ATTR_BASE = " << str << endl;
}
private:
string str;
};
class ATTR1 : public ATTR_BASE {
public:
ATTR1(string str = "none") : ATTR_BASE(str) {}
};
class ATTR2 : public ATTR_BASE {
public:
ATTR2(string str = "none") : ATTR_BASE(str) {}
};
class BASE{
public:
BASE() : attr1("ATTR1"), attr2("ATTR2") {
cout << "class BASE" << endl;
}
BASE(const BASE &a) : attr1(a.attr1), attr2(a.attr2) {
cout << "BASE" << endl;
}
BASE &operator=(const BASE &a) {
attr1 = a.attr1;
attr2 = a.attr2;
cout << "BASE operator = " << endl;
return *this;
}
~BASE() {
cout << "~BASE = " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
class A : public BASE {
public:
A() : attr1("ATTR1 in BASE"), attr2("ATTR2 in BASE") {
cout << "class A" << endl;
}
A &operator=(const A &a) {
this->BASE::operator=(a);
attr1 = a.attr1;
attr2 = a.attr2;
cout << "A operator = " << endl;
return *this;
}
~A() {
cout << "~A() " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
cout << "********************" << endl;
A b(a);
cout << "********************" << endl;
b = a;
cout << "********************" << endl;
return 0;
}
在处理赋值操作的时候和拷贝构造是一样的,如果自己从新写了一个赋值操作,那么我们需要自己把父类的重载,成员属性的重载给实现,我们来看看输出
cout << "~A() " << endl;
}
private:
ATTR1 attr1;
ATTR2 attr2;
};
int main() {
A a;
cout << "********************" << endl;
A b(a);
cout << "********************" << endl;
b = a;
cout << "********************" << endl;
return 0;
}
符合预期。