huangfu Blog
Love Leanote!
Toggle navigation
huangfu Blog
主页
About Me
归档
标签
10继承(构造,析构,拷贝构造,赋值运算符)/名字隐藏机制
2017-10-23 14:03:40
225
0
0
tarena
#继承 ##继承中构造和析构的调用顺序 `构建子类对象`一定会`先调用父类的构造函数` 子类`默认调用父类的无参构造`,也可以`指定调用父类的构造函数` 指定调用的方法是通过`初始化列表指定` `析构函数`的调用顺序`和构造函数调用相反` #include <iostream> using namespace std; class A { int x; public: A() { cout << "A()" << endl; } A(int x):x(x) { cout << "A(int)" << endl; } ~A() { cout << "~A()" << endl; } }; class B:public A { int y; public: B(int x = 0; int y = 0):A(x),y(y) { cout << "B()" << endl; } ~B() { cout << "~B()" << endl; } }; void foo() { B b; } int main() { foo(); /* 调用输出结果: A(int) B() ~B() ~A() */ } ##继承中拷贝构造的调用 当`子类对象触发拷贝构造时`则`默认会调用父类的拷贝构造` 但`一旦给子类提供拷贝构造函数`,则`不在调用父类的拷贝构造函数`,转而去调用父类的构造函数 所以`需要指定调用父类的拷贝构造`,指定方法是使用`拷贝构造`的初始化列表 #include <iostream> using namespace std; class Parent { public: Parent() { cout << "Parent()" << endl; } Parent(const Parent& p) { cout << "Parent(const Parent&)" << endl; } }; clss Child { public: Child() { cout << "Child()" << endl; } /* 指定调用父类的拷贝构造*/ Child(const Child& c):Parent(c) { cout << "Child(const Child&)" << endl; } }; int main() { /* 这里会先调用父类的无参数构造函数,接着调用子类的构造函数 如果想调用有参构造函数则使用初始化列表指定即可*/ Child ca; /* 这里如果子类没有提供拷贝构造,则用父类的无参构造 如果子类提供了拷贝构造,则调用父类的构造函数,如果想让调用父类的拷贝函数, 则需要在子类的拷贝构造的初始化列表中指定*/ Child cb = ca; } ##举例 #include <iostream> using namespace std; /* 人类*/ class Persion { public: string name; int age; int *pdata; // 堆数据 Persion(string name = "", int age):name(name),age(age) { pdata = new int(0); } Persion(const Persion& p) { name = p.name; age = p.age; pdata = new int(0); *pdata = *(p.pdata); } ~Persion() { delete pdata; } }; /* 员工类*/ class Emp { public: double price; int* edata; // 堆数据 Emp(double price = 8000):price(price) { edata = new int(0); } /* 因为员工类中也有堆空间,所以要提供拷贝构造 因为提供了拷贝构造,子类拷贝赋值时不会调用父类拷贝构造而是调用父类无参构造 因为父类也有堆空间,所以要指定调用父类的拷贝构造*/ Emp(const Emp& e):Persion(e) { price = e.price; edata = new int(0); *edata = *(e.edata); } ~Emp() { delete edata; } }; void foo() { /* 下面代码执行完,系统会先调用Persion的构造函数,之后再调用Emp的构造函数*/ Emp ea; /* 下面代码执行完,系统会先调用Persion的拷贝构造,之后在调用Emp的拷贝构造*/ Emp eb = ea; /* 以下4个堆地址各不相同,所以不会出现堆空间共用,内存泄露\double free等一系列问题*/ cout << "ea.pdata=" << ea.pdata << endl; cout << "eb.pdata=" << eb.pdata << endl; cout << "ea.edata=" << ea.edata << end; cout << "ea.edata=" << ea.edata << endl; } int main() { /* 下面函数执行完,系统会调用Emp的析构函数,再调用Persion的析构函数 置于会先调用eb的还是ea的没有研究的意义*/ foo(); } ##赋值运算符函数的继承 当`子类对象触发赋值运算符调用时`则`默认会调用父类的赋值运算符函数` 但`一旦给子类提供赋值运算符函数`,则`不在调用父类的赋值运算符函数函` 所以`需要指定调用父类的赋值运算符函数` `指定方法`是在子类的赋值运算符函数里增加如下一行代码 > Parent::operator=(c) // 调用父类的赋值运算符函数 #include <iostream> using namespace std; class Parent { public: Parent& operator=(const Parent& p) { cout << "operator=(const Parent&)" << endl; } }; class Child { public: /* 一旦子类创建了赋值运算符,则不会再自动调用父类的赋值运算符*/ Child& operator=(const Child& c) { /* 调用父类的赋值运算符*/ Parent::operator=(c); cout << "operaot(const Child&)" << endl; } }; int main() { Child c1; Child c2; c1 = c2; } #名字隐藏机制namehide ##概念 当子类中提供了和父类`同名数据`时,`子类数据会把父类数据隐藏掉`,这种机制叫`名字隐藏` ##举例 #include <iostream> using namespace std; class A { public: int x; void show() { cout << "A show()" << endl; } }; class B:public A { public: int x; void show() { cout << "B show()" << endl; } }; int main() { B b; b.show(); // B show() cout << sizeof b << endl; // 8 } ##如何突破名字隐藏?? > 父类名::数据名 // b.A::show(); ##静态数据的名字隐藏 和普通成员一样 静态数据不占类的内存,也就是和类的大小没有关系
上一篇:
ARM汇编入门
下一篇:
15IO流
0
赞
225 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册