You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中通过接口调用接口程序崩溃原因咨询

问题分析:基类指针访问派生类成员导致崩溃的原因

你想要实现“通过接口访问接口”的无类型感知程序,但代码运行崩溃,核心问题出在基类和派生类的同名成员变量隐藏上,下面详细解释两种崩溃写法的原因:

测试代码

#include <iostream>
#include <string>

using namespace std;

class ToyInteractor {
public:
    ToyInteractor() {};

    virtual void interFunc() = 0;
};

class HorseInteractor : public ToyInteractor {
public:
    HorseInteractor() {};
    ~HorseInteractor() {};

    void interFunc() override { cout << "We made it inside HorseInteractor!" << endl; };
};

class BirdInteractor : public ToyInteractor {
public:
    BirdInteractor() {};
    ~BirdInteractor() {};

    void interFunc() override { cout << "We made it inside BirdInteractor!" << endl; };
};


class Toy {
public:
    Toy() {};

    ToyInteractor *toyInteractor;
    virtual void func() = 0;
};

class Horse : public Toy {
public:
    Horse() {};
    ~Horse() {};

    ToyInteractor *toyInteractor = new HorseInteractor();
    void func() override { cout << "We made it inside Horse!" << endl; };
};

class Bird : public Toy {
public:
    Bird() {};
    ~Bird() {};

    ToyInteractor *toyInteractor = new BirdInteractor();
    void func() override { cout << "We made it inside Bird!" << endl; };
};



int main()
{
    Horse *horse = new Horse();
    Bird *bird = new Bird();

    // Works as expected
    horse->func();
    bird->func();
    cout << endl;

    // Also works of course
    horse->toyInteractor->interFunc();
    bird->toyInteractor->interFunc();
    cout << endl;


    // Now suppose we do not know the exact type, but we know it surely has a toy-specific toyInteractor:
    Toy *someToy = horse;

    // Works fine:
    someToy->func();

    // 1. idea: Crashes:
//    someToy->toyInteractor->interFunc();

    // 2. idea: Also crashes:
//    ((HorseInteractor*)(someToy->toyInteractor))->interFunc();

    return 0;
}

崩溃原因详解

1. someToy->toyInteractor->interFunc(); 崩溃原因

你在基类Toy中声明了ToyInteractor *toyInteractor;,但派生类Horse和Bird里又重新定义了同名的toyInteractor变量——这属于成员隐藏,基类和派生类的toyInteractor是完全独立的两个变量:

  • 当用Horse* horse访问时,操作的是Horse类自己定义的、已经初始化的toyInteractor;
  • 但当转换为Toy* someToy后,someToy->toyInteractor访问的是基类Toy中那个未初始化的野指针(基类构造函数没有给它赋值,内存地址随机)。
    调用interFunc()时,通过野指针访问非法内存,直接触发崩溃。

2. ((HorseInteractor*)(someToy->toyInteractor))->interFunc(); 崩溃原因

这种写法只是给野指针做了强制类型转换,但本质还是操作基类里那个未初始化的无效地址。类型转换只能改变编译器对指针类型的认知,无法把野指针变成有效指针,因此调用成员函数依然会访问非法内存,导致崩溃。

修复方案

解决核心是让基类和派生类共用同一个toyInteractor变量,不要隐藏:

  • 删除派生类Horse和Bird中重新声明的ToyInteractor *toyInteractor = ...;;
  • 在派生类构造函数中给基类的toyInteractor赋值:
class Horse : public Toy {
public:
    Horse() {
        toyInteractor = new HorseInteractor();
    };
    ~Horse() {};

    void func() override { cout << "We made it inside Horse!" << endl; };
};

class Bird : public Toy {
public:
    Bird() {
        toyInteractor = new BirdInteractor();
    };
    ~Bird() {};

    void func() override { cout << "We made it inside Bird!" << endl; };
};

这样Toy* someToy访问的toyInteractor就是派生类构造时初始化的有效指针,调用interFunc()就能正常执行。

内容的提问来源于stack exchange,提问作者LimeAndConconut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 10:03:13