转换与继承
派生类对象也是基类对象。这意味着在使用基类的地方可以用派生类来替换。
派生类到基类的转换
1.当派生类以public方式继承基类时,编译器可自动执行的转换(向上转换upcasting安全转换)
1.1 派生类对象指针自动转化为基类对象指针
1.2 派生类对象引用自动转化为基类对象引用
1.3 派生类对象自动转化为基类对象(特有的成员消失)
2.当派生类以private/protected方式继承基类时
2.1 派生类对象指针(引用)转化为基类对象指针(引用)需用强制类型转化。但不能用static_cast,要用reinterpret_cast
### 回顾C++转型(static_cast、reinterpret_cast、const_cast、dynamic_cast)
2.2 不能把派生类对象强制转化为基类对象
基类到派生类的转换
1.基类对象指针(引用)可用强制类型转化为派生类对象指针(引用),而基类对象无法执行这类转换。
2.向下转型不安全,没有自动转换的机制。
#include <iostream>
using namespace std;
class Employee
{
public:
Employee(const string& name, const int age, const int deptno) : name_(name), age_(age), deptno_(deptno)
{
cout << "Employee ..." << endl;
}
~Employee()
{
cout << "~Employee ..." << endl;
}
private:
string name_;
int age_;
int deptno_;
};
class Manager : public Employee
{
public:
Manager(const string& name, const int age, const int deptno, int level) : Employee(name, age, deptno), level_(level)
{
cout << "Manager ..." << endl;
}
~Manager()
{
cout << "~Manager ..." << endl;
}
private:
int level_;
};
class Manager2 : private Employee
{
public:
Manager2(const string& name, const int age, const int deptno, int level) : Employee(name, age, deptno), level_(level)
{
cout << "Manager2 ..." << endl;
}
~Manager2()
{
cout << "~Manager2 ..." << endl;
}
private:
int level_;
};
int main()
{
Employee e1("jack", 25, 20);
Manager m1("ma", 30, 20, 10);
Manager2 m2("yun", 50, 40, 20);
Employee* pe;
Manager* pm;
Manager2* pm2;
cout << "派生类到基类的转换" << endl;
cout << "public..." << endl;
cout << endl;
pe = &e1;
pm = &m1;
pe = &m1;
e1 = m1;
cout << "private/protected..." << endl;
cout << endl;
pm2 = &m2;
pe = reinterpret_cast<Employee*>(pm2);
cout << "***************" << endl;
cout << "基类到派生类的转换" << endl;
cout << endl;
pm = static_cast<Manager*>(pe);
pm2 = static_cast<Manager2*>(pe);
return 0;
}
多重继承
1.单重继承:一个派生类最多只能有一个基类
2.多重继承:一个派生类可以有多个基类
class 类名:继承方式 基类1, 继承方式 基类2,...
{...};
派生类同时继承多个基类的成员,更好的软件重用
可能会有大量的二义性,多个基类中可能包含同名变量或函数
3.多重继承中解决访问歧义的方法
基类名::数据成员名(或成员函数(参数表))
明确指明要访问定义于哪个基类中的成员
虚继承与虚基类
1.当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性------采用虚基类来解决。
2.虚基类的引入
用于有共同基类的场合
3.声明
以virtual修饰说明基类
eg:class B1:virtual public BB
4.作用
4.1主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题。
4.2为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。
虚基类及其派生类构造函数
1.虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
2.在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始列表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该基类的默认构造函数。
3.在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。
#include <iostream>
using namespace std;
class Furniture
{
public:
Furniture(const int weight) : weight_(weight)
{
cout << "Furniture ..." << endl;
}
~Furniture()
{
cout << "~Furniture ..." << endl;
}
int weight_;
};
class Bed : virtual public Furniture
{
public:
Bed(const int weight) : Furniture(weight)
{
cout << "Bed ..." << endl;
}
void Sleep()
{
cout << "Sleep ..." << endl;
}
~Bed()
{
cout << "~Bed ..." << endl;
}
};
class Sofa : virtual public Furniture
{
public:
Sofa(const int weight) : Furniture(weight)
{
cout << "Sofa ..." << endl;
}
void WatchTV()
{
cout << "WatchTV ..." << endl;
}
~Sofa()
{
cout << "~Sofa ..." << endl;
}
};
class SofaBed : public Bed, public Sofa
{
public:
SofaBed(int weight) : Bed(weight), Sofa(weight), Furniture(weight)
{
cout << "SofaBed ..." << endl;
}
void FoldIn()
{
cout << "FoldIn ..." << endl;
}
void FoldOut()
{
cout << "FoldOut ..." << endl;
}
~SofaBed()
{
cout << "~SofaBed ..." << endl;
}
};
int main()
{
SofaBed softbed(10);
softbed.weight_ = 20;
return 0;
}