【C++学习】对象特性--继承

一、继承的方式

基础语句

cpp 复制代码
//类A继承类B,B为基类(父类),A为派生类(子类)
//class A:pulic B{};
#include <iostream> //标准输入输出控件
#include <iomanip>
#include <string>  //使用string声明字符串时必须包含
#include <cstdlib> //汉化
using namespace std;
/*继承基本语句*/

class BaseClass
{
public:
    void baseClassCout() { cout << "父类" << endl; };
};

class SonClass1 : public BaseClass
{
public:
    void sonClassCout() { cout << "子类1" << endl; };
};

void test1()
{
    SonClass1 son1;
    son1.baseClassCout();
    son1.sonClassCout();
};

int main()
{
    system("chcp 65001 >nul"); // 汉化
    // using std::cout;
    test1();

    return 0;
}

继承方式

复制代码
公共继承 public
保护继承 protected
私有继承 private

各继承方式的特点

使用public继承时,父类的public成员在子类中依旧为public成员,父类的protected成员在子类中为protected成员,按照此规律,继承特点如下表所示

注意:父类的 private成员 三种继承的子类都不能访问

复制代码
公共继承 public     父 public->子 public      父 protected->子 protected
保护继承 protected  父 public->子 protected   父 protected->子 protected
私有继承 private    父 public->子 private     父 protected->子 private

二、父子实例的构造函数与析构函数执行顺序

复制代码
父类构造函数->子类构造函数->子类析构函数->父类析构函数
cpp 复制代码
class Parent {
public:
    Parent() { cout << "Parent 构造函数" << endl; }
    ~Parent() { cout << "Parent 析构函数" << endl; }  // 非虚析构(仅演示顺序)
};

class Child : public Parent {
public:
    Child() { cout << "Child 构造函数" << endl; }
    ~Child() { cout << "Child 析构函数" << endl; }
};

int main() {
    Child c;  // 创建子类对象,出作用域时自动销毁
    return 0;
}

三、父子实例同名成员访问方式

访问同名变量

cpp 复制代码
#include <iostream>
using namespace std;

class Parent {
public:
    int num = 10;  // 父类成员变量
};

class Child : public Parent {
public:
    int num = 20;  // 子类同名成员变量(隐藏父类的num)
};

int main() {
    Child c;
    cout << c.num << endl;          // 直接访问:子类的num → 输出 20
    cout << c.Parent::num << endl;  // 显式指定父类作用域:父类的num → 输出 10

    Child* ptr = &c;
    cout << ptr->num << endl;       // 指针访问子类num → 20
    cout << ptr->Parent::num << endl; // 指针访问父类num → 10
    return 0;
}

访问同名函数

若父子类存在同名非虚函数(参数列表可不同),子类函数会隐藏父类所有同名函数(无论参数是否相同),直接调用时默认执行子类函数

cpp 复制代码
class Parent {
public:
    void func() { cout << "Parent::func()" << endl; }
    void func(int x) { cout << "Parent::func(int) " << x << endl; }  // 重载函数
};

class Child : public Parent {
public:
    void func() { cout << "Child::func()" << endl; }  // 隐藏父类所有func()
};

int main() {
    Child c;
    c.func();          // 调用子类func() → 输出 Child::func()
    // c.func(10);     // 编译报错!子类隐藏了父类的func(int),无法直接调用
    
    // 调用父类的func()和func(int)
    c.Parent::func();       // 输出 Parent::func()
    c.Parent::func(10);     // 输出 Parent::func(int) 10
    return 0;
}

四、多继承语法

cpp 复制代码
#include <iostream>
using namespace std;

// 父类1:表示"能跑"的特性
class Runable {
public:
    void run() {
        cout << "可以奔跑" << endl;
    }
};

// 父类2:表示"能飞"的特性
class Flyable {
public:
    void fly() {
        cout << "可以飞翔" << endl;
    }
};

// 子类:同时继承 Runable 和 Flyable(如"飞毯"既可以跑也可以飞)
class Carpet : public Runable, public Flyable {
public:
    void display() {
        cout << "这是一个神奇的飞毯:" << endl;
    }
};

int main() {
    Carpet c;
    c.display();  // 子类自身方法
    c.run();      // 继承自 Runable 的方法
    c.fly();      // 继承自 Flyable 的方法
    return 0;
}

五、菱形继承(钻石继承)

当多继承中出现 "两个父类继承自同一个基类" 的情况,会导致子类中存在间接基类的多份副本,引发数据冗余和访问歧义

问题演示

cpp 复制代码
// 顶层基类
class Object {
public:
    int id;
};

// 中间父类 A 和 B,都继承 Object
class A : public Object {};
class B : public Object {};

// 子类 C 同时继承 A 和 B,导致 C 中包含两份 Object::id
class C : public A, public B {};

int main() {
    C c;
    // c.id = 10;  // 编译报错:歧义(A::id 还是 B::id?)
    c.A::id = 10;  // 需显式指定,繁琐且不合理
    c.B::id = 20;
    return 0;
}

虚继承解决

通过在中间父类的继承方式前加 virtual 关键字,确保顶层基类在子类中只存在一份副本,避免冗余和歧义

cpp 复制代码
class Object {
public:
    int id;
};

// 中间父类用虚继承
class A : virtual public Object {};  // 虚继承 Object
class B : virtual public Object {};  // 虚继承 Object

// 子类 C 继承 A 和 B,Object 仅一份副本
class C : public A, public B {};

int main() {
    C c;
    c.id = 10;  // 无歧义,直接访问唯一的 id
    return 0;
}
相关推荐
for_ever_love__18 分钟前
UI学习:UISearchController基础了解和应用
学习·ui·ios·objective-c
心中有国也有家28 分钟前
GE图引擎深度解析——CANN的计算图优化与执行引擎
人工智能·pytorch·python·学习·numpy
isyangli_blog2 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008112 小时前
FastAPI APIRouter
开发语言·python
Benszen2 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆2 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木2 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
GHL2842710902 小时前
换脸工作流学习
学习·ai
MC皮蛋侠客2 小时前
C++17 多线程系列(五):C++17 并行算法——从串行到并行的零成本迁移
c++·多线程
_李小白2 小时前
【android opencv学习笔记】Day 28: 滤波算法之中值滤波器
android·opencv·学习