【C++】继承 ⑥ ( 继承中的构造函数和析构函数 | 类型兼容性原则 | 父类指针 指向 子类对象 | 使用 子类对象 为 父类对象 进行初始化 )

2023-10-23 19:25:31 浏览数 (2)

一、public 公有继承 - 示例分析

1、类型兼容性原则

类型兼容性原则 : C 的 " 类型兼容性原则 “ 又称为 ” 赋值兼容性原则 " ;

子类代替父类 : 需要 基类 ( 父类 ) 对象的 地方 , 都可以使用 " 公有继承 " 的 派生类 ( 子类 ) 对象 替代 , 该 派生类 ( 子类 ) 得到了 除 构造函数 和 析构函数 之外的 所有 成员变量 和 成员方法 ;

功能完整性 : " 公有继承 " 的 派生类 ( 子类 ) 本质上 具有 基类 ( 父类 ) 的 完整功能 , 使用 基类 可以解决的问题 , 使用 公有继承派生类 都能解决 ;

特别注意 : " 保护继承 " 和 " 私有继承 " 的 派生类 , 是 不具有 基类 的 完整功能的 , 因为 最终继承 后的派生类 , 无法在 类外部调用 父类的 公有成员 和 保护成员 ;

2、类型兼容性原则应用场景

" 类型兼容性原则 " 应用场景 :

  • 直接使用 : 使用 子类对象 作为 父类对象 使用 ;
  • 赋值 : 将 子类对象 赋值给 父类对象 ;
  • 初始化 : 使用 子类对象 为 父类对象 初始化 ;
  • 指针 : 父类指针 指向 子类对象 , 父类指针 值为 子类对象 在 堆内存 的地址 , 也就是 将 子类对象 地址 赋值给 父类类型指针 ;
  • 引用 : 父类引用 引用 子类对象 , 将 子类对象 赋值给 父类类型的引用 ;

二、类型兼容性原则 - 示例分析


定义父类 Parent , 子类 Child ;

代码语言:javascript复制
class Parent {
public:
    void funParent()
    {
        cout << "父类 funParent 函数" << endl;
    }

private:
    int c;
};

// 子类 公有继承 父类
class Child : public Parent {
public:
    void funChild() 
    {
        cout << "子类 funChild 函数" << endl;
    }
};

1、父类指针 指向 子类对象

定义 一个子类对象 Child child ;

定义父类的指针 , 将 指针 指向 子类对象 的地址 , 这是合法的 ;

代码示例 :

代码语言:javascript复制
    // 父类对象
    Parent parent;
    // 子类对象
    Child child;

    // I. 类型兼容性原则 : 父类指针 指向 子类对象
    Parent* p_parent2 = NULL;
    p_parent2 = &child;

该原则的应用场景如下 : 定义函数 , 接收 父类指针 或 父类引用 , 此处可以直接传入 子类指针 或 子类引用 ;

代码语言:javascript复制
// 函数接收父类指针类型
// 此处可以传入子类对象的指针
void fun_pointer(Parent* obj)
{
    obj->funParent();
}

// 函数接收父类引用类型
// 此处可以传入子类对象的引用
void fun_reference(Parent& obj)
{
    obj.funParent();
}

2、使用 子类对象 为 父类对象 进行初始化

定义父类对象 , 可以直接使用 子类对象 进行初始化操作 ;

代码语言:javascript复制
    // II. 类型兼容性原则 : 使用 子类对象 为 父类对象 进行初始化
    Parent parent = child;

3、完整代码示例

代码语言:javascript复制
#include "iostream"
using namespace std;

class Parent {
public:
    void funParent()
    {
        cout << "父类 funParent 函数" << endl;
    }

private:
    int c;
};

// 子类 公有继承 父类
class Child : public Parent {
public:
    void funChild() 
    {
        cout << "子类 funChild 函数" << endl;
    }
};

// 函数接收父类指针类型
// 此处可以传入子类对象的指针
void fun_pointer(Parent* obj)
{
    obj->funParent();
}

// 函数接收父类引用类型
// 此处可以传入子类对象的引用
void fun_reference(Parent& obj)
{
    obj.funParent();
}

int main() {

    // 父类对象
    Parent parent;
    // 子类对象
    Child child;


    // 父类对象 可以调用 父类公有函数
    parent.funParent();
    // 子类对象 可以调用 子类自身公有函数
    child.funChild();
    // 子类对象 可以调用 父类公有函数
    child.funParent();

    // 将指向子类对象的指针传给接收父类指针的函数
    // 也是可以的
    fun_pointer(&child);

    // 接收父类引用 , 此处传入子类引用
    fun_reference(child);


    // 赋值兼容性原则 : 
    cout << "n赋值兼容性原则示例 : n" << endl;


    // 常规操作 : 父类指针 指向 父类对象
    Parent* p_parent = NULL;
    p_parent = &parent;
    // 通过父类指针调用父类函数
    p_parent->funParent();

    // 将指向子类对象的指针传给接收父类指针的函数
    // 也是可以的
    fun_pointer(p_parent);

    // 接收父类引用参数
    fun_reference(*p_parent);


    // I. 类型兼容性原则 : 父类指针 指向 子类对象
    Parent* p_parent2 = NULL;
    p_parent2 = &child;
    // 通过父类指针调用父类函数
    p_parent2->funParent();


    // II. 类型兼容性原则 : 使用 子类对象 为 父类对象 进行初始化
    Parent parent3 = child;
    
    

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :

代码语言:javascript复制
父类 funParent 函数
子类 funChild 函数
父类 funParent 函数
父类 funParent 函数
父类 funParent 函数

赋值兼容性原则示例 :

父类 funParent 函数
父类 funParent 函数
父类 funParent 函数
父类 funParent 函数
Press any key to continue . . .

0 人点赞