为什么在这段代码中派生类不能调用受保护的成员函数? [英] Why can't a derived class call protected member function in this code?

查看:817
本文介绍了为什么在这段代码中派生类不能调用受保护的成员函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  #include< iostream> 

class Base
{
protected:
void somethingProtected()
{
std :: cout< lala< std :: endl;
}
};

class Derived:public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); //这不编译
somethingProtected(); //但这是罚款
}
};

int main()
{
Derived d;
d.somethingDerived();
return 0;
}



我认为可能只有受保护的成员



但是:

pre> class Derived:public Base
{
public:

void somethingDerived(派生& d)
{
d.somethingProtected(); //编译即使d是
//可能不同的实例
}

void somethingDerived(Base& b)
{
b.somethingProtected (); // This does not
}
};

我感到有些厌恶,因为我一直在C ++编程一段时间,找不到此行为的任何解释。



编辑:



相同或不同的实例:

  int main()
{
派生d1,d2; //两个不同的实例
d1.somethingDerived(d2); // this compiles fine
d1.somethingDerived(d1); //这编译精细
return 0;
}

EDIT2:



看来,当涉及访问权限时,使用类的实例并不重要:

  class Base 
{
public:
void something(Base& b)//另一个实例
{
++ ba; //但可以输入私有成员
}

private:
int a;
};


解决方案

即使C ++中的访问控制工作在每个类 protected 访问说明符有一些特殊性。



语言规范想要以确保您正在访问属于派生类的某些基本子对象的受保护成员。你不应该能访问基本类型的一些不相关的独立对象的受保护成员。特别是,您无法访问基本类型的独立对象的受保护成员。您只能访问被嵌入到派生对象中的基础对象的受保护成员作为基本子对象。



为此,您必须通过 pointer-> member 语法, reference.member object.member访问受保护的成员语法,其中指针/引用/对象引用派生的类。



这意味着在您的示例中,protected somethingProtected()无法通过 Base 对象, Base * 指针或 Base& 引用, 派生的对象,派生的* 指针和派生的& 。允许您的普通 somethingProtected()访问,因为它只是 this-> somethingProtected()的缩写的类型为 Derived *



b.somethingProtected()违反上述要求。



请注意,按照上述规则

  void Derived :: somethingDerived()
{
Base * b = this;
b-> somethingProtected(); // ERROR
this-> somethingProtected(); // OK
}

第一次调用也会失败,即使两者都尝试访问同一实体。


#include <iostream>

class Base
{  
protected:
    void somethingProtected()
    {
        std::cout << "lala" << std::endl;
    }
};

class Derived : public Base
{
public:
    void somethingDerived()
    {
        Base b;
        b.somethingProtected();    // This does not compile
        somethingProtected();      // But this is fine
    }
};

int main()
{
    Derived d;
    d.somethingDerived();
    return 0;
}

I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.

But:

class Derived : public Base
{
public:

    void somethingDerived(Derived& d)
    {
        d.somethingProtected();  // This compiles even though d is
                                 // potentially a different instance
    }

    void somethingDerived(Base& b)
    {
        b.somethingProtected();  // This does not
    }
};

I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.

EDIT:

It doesn't matter if it is the same or a different instance:

int main()
{
    Derived d1, d2;          // Two different instances
    d1.somethingDerived(d2); // This compiles fine
    d1.somethingDerived(d1); // This compiles fine
    return 0;
}

EDIT2:

It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:

class Base
{
public:
    void something(Base& b)  // Another instance
    {
        ++b.a;               // But can enter private members
    }

private:
    int a;
};

解决方案

Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.

The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.

For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.

This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.

b.somethingProtected() violates the above requirements.

Note that in accordance with the above rules in

void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}

the first call will also fail while the second one will compile, even though both are trying to access the same entity.

这篇关于为什么在这段代码中派生类不能调用受保护的成员函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆