【问题标题】:Error while accessing derived class resources by base class object通过基类对象访问派生类资源时出错
【发布时间】:2020-09-23 19:14:02
【问题描述】:

我有一个名为 Base 的基类和一个名为 Derived 的 Base 派生类, 基类指针可以指向派生类对象,也可以访问它的资源,但是这样做会出错。

class Base
{
public:
    int a;
};

class Derived : public Base
{
public:
    float b;
    void DoSomething()
    {
         cout<<"Derived";
    }
};

int main()
{
    Base * pBase = new Derived();
    pBase->DoSomething();
    pBase->a = 5; 
    pBase->b = 0.2f; 
    return 0;
}

这给了我一个错误

main.cpp: In function ‘int main()’:
main.cpp:34:25: error: ‘class Base’ has no member named ‘DoSomething’
     pBase->DoSomething();
                         ^
main.cpp:36:12: error: ‘class Base’ has no member named ‘b’
     pBase->b = 0.2f;
            ^

如果它太基础,请原谅我,我是 C++ 的初学者

【问题讨论】:

  • 如果您使用Derived 作为Base,它会受到Base 所知道的限制。 Base 没有DoSomething 所以Base 不能使用DoSomething
  • 但是看到这个Base * pBase = new Derived();我们可以做到这一点。我研究过这是允许的,即基类指针可以存储对其派生类的引用
  • Derivedis-aBase。它知道Base 知道的一切,并且可以用作Base。但是Base 不知道Derived 知道什么。 Base* 可能指向 Derived,也可能指向具有不同功能的 AlsoDerivedLook into virtual methods 如果您希望 Base 中的行为可以由派生自 Base 的类指定。

标签: c++ pointers inheritance derived-class base-class


【解决方案1】:

是的,您可以使用指向 Derived 类的 Base 指针,但是,Base 指针必须知道方法才能选择最适合调用的方法,如果 Base 指针没有知道这些变量和函数的存在,它不能调用它们。

Corrected code:

class Base
{
public:
    int a;
    float b;
    virtual ~Base(){} //virtual destructor required
    virtual void DoSomething() //implementing DoSomething in base class
    {
        std::cout << "Base";
    }
};

class Derived : public Base
{
public:
    void DoSomething() override //override DoSomething() in base class
    {
         std::cout<<"Derived";
    }
};
Base * pBase = new Derived();
//Base will choose the most suited DoSomething(), depending where it's pointing to
pBase->DoSomething(); 
pBase->a = 5;
pBase->b = 0.2f; 

输出:

Derived

编辑:

正如您在评论部分所建议的那样,强制转换派生类将在这种特定情况下起作用,但它通常会揭示设计不佳的代码,正如 @user4581301's comment 所指出的那样,还要注意 link provided 有一些原因为什么这不是最好的主意。

正如我所说,如果必须这样做,请改用dynamic_cast&lt;&gt;()

请注意,在任何情况下,您仍然需要虚拟析构函数来正确实现多态性。

虚拟析构函数

通过指向基类的指针删除对象会调用未定义的行为,除非基类中的析构函数是虚拟的。

这还不是全部,请查看this link

【讨论】:

  • 经过一点研究后,我发现我正在寻找静态演员 static_cast&lt;Derived*&gt;(pBase)-&gt;DoSomething();,如果您可以编辑您的答案,解释我可以接受这个问题的答案。你还可以提一下这样做有什么缺点吗
  • @FarhanAhmed 您应该避免从基础转换为派生。有时你必须,但更多时候你在设计中存在缺陷。如果你必须经常这样做,那么类根本不应该有继承关系。
  • @FarhanAhmed,虽然这在这种特定情况下有效,但完全不建议这样做,这肯定会导致设计非常糟糕的代码,但如果你必须这样做,dynamic_cast 更好。
  • 考虑这一点:为了以这种方式使用演员表,您必须绝对确定 Base* 指向 Derived,如果您绝对确定这一点,为什么要使用Base 呢?
  • @FarhanAhmed,我在回答中添加了更多信息,请务必查看。
猜你喜欢
  • 2015-05-23
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多