• public 继承的派生类和基类具有父子关系
  • 具有父子关系的派生类指针或对象可以不用进行强制类型转换,直接赋值给基类指针或引用
  • public 继承的 派生类指针 要通过强制类型转换(reinterpret_cast 或者 (Base*))的方式才能赋值给 父类指针
  • 派生类内部和派生类的友元函数 中可以用 父类指针父类引用 直接指向 子类指针或对象,也可以直接将 子类对象赋值给父类对象
  • 在其它地方,不能将 public 继承派生类对象 赋值给父类对象或引用,提示 不可访问的基类,但可以通过 (Base&&) 这种强制类型转换的方式将派生类对象转换为基类的右值引用,且支持多态(VS 无法编译通过
  • 父类的析构函数必须是虚函数
  • 即使父类的析构函数不是虚函数,在栈上定义的子类对象销毁时也会调用父类的析构函数
  • 指针、右值引用、左值引用都支持多态
  • 对象间赋值转换不支持多态

C++-父类与子类

#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;
}