public
继承的派生类和基类具有父子关系- 具有父子关系的派生类指针或对象可以不用进行强制类型转换,直接赋值给基类指针或引用
- 非
public
继承的 派生类指针 要通过强制类型转换(reinterpret_cast
或者(Base*)
)的方式才能赋值给 父类指针 - 在 派生类内部和派生类的友元函数 中可以用 父类指针 或 父类引用 直接指向 子类指针或对象,也可以直接将 子类对象赋值给父类对象
- 在其它地方,不能将 非
public
继承 的 派生类对象 赋值给父类对象或引用,提示 不可访问的基类,但可以通过(Base&&)
这种强制类型转换的方式将派生类对象转换为基类的右值引用,且支持多态(VS
无法编译通过) - 父类的析构函数必须是虚函数
- 即使父类的析构函数不是虚函数,在栈上定义的子类对象销毁时也会调用父类的析构函数
- 指针、右值引用、左值引用都支持多态
- 对象间赋值转换不支持多态
#include <iostream>
using namespace std;
class A{
public:
~A() = default; //1)
// A(){} //2)
virtual void f(){
cout << "A::f()\n";
}
};
class B: A{
friend void friendFun();
void f(){
cout << "B::f()\n";
}
public:
A* getA(){ // 派生类内部函数可构成父子关系
return this;
}
};
void friendFun(){ // 派生类友元函数内可构成父子关系
A* p = new B;
p->f();
}
int main()
{
// A* p = new B; // error: ‘A’ is an inaccessible base of ‘B’
A* p = (A*)new B; // right
B b;
A* pp = b.getA(); //
pp->f(); // B::f()
friendFun(); // B::f()
A* ppp = B().getA();
ppp->f(); // 注意:
// 1)当父类是默认析构函数时,输出:B::f()
// 2)当父类写析构函数时,输出:A::f()
return 0;
}
class A {
int x, y;
public:
virtual ~A() {
cout << "~A()\n";
}
int getx() {
return x;
}
virtual int vf() const {
return 1;
}
protected:
int gety() {
return y;
}
};
class B : protected A {
friend int main();
bool visible;
public:
~B() {
cout << "~B()\n";
}
using A::gety;
A* getFather(){
return this;
}
private:
virtual int vf() const {
// 子类内部不受继承方式的影响
const A *pa = this; // 将子类指针赋值给父类指针
const A& ra = *this; // 将父类引用指向子类对象
A a = *this; // 将子类对象赋值给父类对象
// 父类对象 a 生命期在函数结束后结束
// 输出:~A()
cout << "in B::vf() A::vf():" << A::vf() << endl;
cout << "in B::vf() a.vf():" << a.vf() << endl;
return 2;
}
};
int main()
{
// 指针、右值引用、左值引用都支持多态
// 对象间赋值转换不支持多态
// 1. 对象间赋值转换
// 非友元、非 public 继承不能进行派生类对象和基类对象之间的转换:
// 强制类型转换也不行 error: ‘A’ is an inaccessible base of ‘B’
// 编译时根据类型定义静态的检查语义
// class A 和 class B 是父子关系时才可以用下面的赋值
// 或者将 main() 声明为 class B 的友元
A a = B(); // 等同于 A a = static_cast<A>(B());
// 等同于 A a = (A)B();
// B() 产生一个常量对象(右值),生命期在 ;号后结束,自动释放
// a 生命期在函数结束后结束,所以控制台输出为:
// ~B()
// ~A()
// ~A()
cout << a.vf() << endl; // 输出 1
A* pa = B().getFather(); // B() 产生一个常量对象(右值),生命期在 ;号后结束,自动释放
// 输出:
// ~B()
// ~A()
cout << pa->vf() << endl; // 输出 1
// 2. 右值引用
A&& ra1 = B(); // B() 是常量(右值)是无址的
// 右值引用 ra1 生命期在函数结束后结束,输出为:
// ~B()
// ~A()
cout << ra1.vf() << endl; // 输出:2
cout << &ra1 << endl; // 右值引用变量 ra 为左值,所以有地址
// 输出为:0x7fff66900b20
// 非友元、非 public 继承时可进行强制转换
// A&& ra2 = (A&&)B(); // OK
// VS error C4789: 缓冲区“$S1”(大小为 16 字节)将溢出;24 字节将在偏移 0 时开始写入
// A&& ra3 = reinterpret_cast<A&&>(B()); // error: invalid cast of an rvalue expression of type ‘B’ to type ‘A&&’
// A&& ra4 = static_cast<A&&>(B()); // error: ‘A’ is an inaccessible base of ‘B’
// A&& ra5 = dynamic_cast<A&&>(B()); // error: ‘A’ is an inaccessible base of ‘B’
// cout << ra2.vf() << endl; // 输出 2
// 3. 常量引用
// 将父类引用指向子类对象
//A& a = B(); // error:非常量引用的初始值必须为左值(可以取地址的)
const A& ca = B(); // OK: 常量引用 ca 生命期在函数结束后结束,输出为:
// ~B()
// ~A()
// 非父子关系时可进行强制类型转换
// const A& ca = (const A&)B(); // OK
// const A& ca = static_cast<const A>(B()); // error: ‘A’ is an inaccessible base of ‘B’
// const A& ca = dynamic_cast<const A>(B()); // error: cannot dynamic_cast ‘B()’ (of type ‘class B’) to type ‘const class A’ (target is not pointer or reference)
// const A& ca = reinterpret_cast<const A>(B()); // error: invalid cast from type ‘B’ to type ‘const A’
// const A& ca = reinterpret_cast<const A&>(B()); // error: invalid cast of an rvalue expression of type ‘B’ to type ‘const A&’
cout << ca.vf() << endl; // 输出为:2
// 4. 非常量引用
A& la = *(new B());
// 非父子关系时可进行强制类型转换
// A& la = *((A*)new B());
cout << la.vf() << endl; // 输出 2
delete &la;
// 5. 将子类指针赋值给父类指针
A *pa0 = new B();
cout << pa0->vf() << endl; // 输出 2
// 非父子关系时进行强制类型转换
// B *pb = new B();
// A *pa1 = static_cast<A*>(pb); // error: ‘A’ is an inaccessible base of ‘B’
// A *pa2 = dynamic_cast<A*>(pb); // error: ‘A’ is an inaccessible base of ‘B’
// A *pa3 = (A*)pb; // OK
// A *pa4 = reinterpret_cast<A*>(pb); // OK
// cout << pa3->vf() << endl; // 2
// cout << pa4->A::vf() << endl; // 1
// delete pa3; // 如果 class A 不是虚析构,此处只输出 ~A()
delete pa0;
return 0;
}