通过基类的指针,我们无法访问派生类特定成员

时间:2017-04-12 08:58:52

标签: c++ class

A Base Class pointer can point to a derived class object. Why is the vice-versa not true?

该线程表示我们不能使派生类指向基类,因为派生类可能无法访问基类的所有成员。

反过来也是如此。 基类甚至不能访问特定于派生类的成员。

#include <iostream>

using namespace std;

class BaseClass
{
public:
    virtual void baseFx();
};

void BaseClass::baseFx()
{
    std::cout << "From base virtual function\n";
}

class DerivedClass : public BaseClass
{
public:
    void baseFx();
    void h() { std::cout << "From derived class. h()\n"; }
};

void DerivedClass::baseFx()
{
    std::cout << "From derived virtual function\n";
}

int main()
{
    BaseClass* objBaseclassB = new DerivedClass();
    objBaseclassB->baseFx (); // Calls derived class's virtual function.
    objBaseclassB->h(); // error: 'class BaseClass' has no member named 'h'.

    return 0;
}

那么,为什么限制仅适用于派生类?为什么考虑到上述逻辑不允许这样做? DerivedClass* objBaseclassC = new BaseClass();

2 个答案:

答案 0 :(得分:1)

将派生类对象分配给基类指针是有效的,也是多态的基石。

是的,Derived类可能有其他成员无法通过基类指针访问,这是可以的,因为你,程序员正在做这样的任务,同时完全意识到你无法访问这些成员。你纯粹是出于多态的目的。这意味着您将只调用虚函数,这些函数将使用vtable根据指针指向的对象调用正确的覆盖。

但是,将基类指针强制转换回派生类指针并不简单。您需要类型信息,并且只有Base类是多态的(即具有虚函数)并且您要转换的类是从Base类派生的。这项精确检查由dynamic_cast执行。 dynamic_cast检查是否可以进行向下转换,如果有效则返回Derived类指针。否则返回nullptr

来到你的最后一个问题: DerivedClass* objBaseclassC = new BaseClass();无效,因为访问DerivedClass中的任何“额外”成员会导致崩溃。

但是当你这样做的时候 BaseClass* derivedPointer = new DerivedClass();这样的构造将导致编译时错误。

答案 1 :(得分:0)

让我试着以合乎逻辑的方式解释这一点。

OO编程中的继承用于实现&#34;是&#34;不同阶级之间的关系。例如。如果有一个类动物和一个类狗,我们知道一只狗&#34;是一个&#34;动物和狗将扩展动物。因此,它显然会表现出很多功能(例如,吃() - 功能),这在其他动物(类)中很常见。因此,我们倾向于将这些公共代码放入基类Animal中,并保留特定于派生类中每个子类的代码。 (例如,狗的树皮())

因此,只允许基类类型指针指向派生类对象,即 动物* horse1 =新马(); 毕竟马是动物。 另一种方式并不合理,因为每只动物都不一定是马。

PS:就C ++而言,继承主要只是公共代码的重用机制。