为什么可以';在这段代码中是否有派生类调用受保护的成员函数? 我觉得有点恶心,因为我在C++编程了一段时间,但是我找不到任何解释这个行为。< /P>

为什么可以';在这段代码中是否有派生类调用受保护的成员函数? 我觉得有点恶心,因为我在C++编程了一段时间,但是我找不到任何解释这个行为。< /P>,c++,oop,C++,Oop,编辑: 无论是相同的实例还是不同的实例: class Derived : public Base { public: void somethingDerived(Derived& d) { d.somethingProtected(); // This compiles even though d is // potentially a different instance }

编辑:

无论是相同的实例还是不同的实例:

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
    }
};
编辑2:

似乎在访问权限方面,使用类的实例并不重要:

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

我相信您对如何访问基类成员有些困惑。 只有这样:

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

private:
    int a;
};
在您的示例中,您试图访问另一个实例的受保护成员

派生实例将可以访问它自己的受保护成员,但不能访问另一个类实例受保护的成员,这是出于设计考虑

事实上,访问另一个类的受保护成员、从另一个实例成员或从主函数访问受保护成员实际上都是公共访问

(查找访问说明符表以查看不同的级别)

两个例子证明了同一件事,例如:

class Derived : public Base
void drivedMethod() {
    Base::baseMethod();
}
在这里,您的派生类获取b作为参数,因此它获取另一个base实例,因为b.somethingProtected不是公共的,所以它将不兼容

这将包括:

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

第二个示例符合要求,因为您正在访问另一个d类上的公共方法

void somethingDerived()
{
   Base::somethingDerived();

派生的
类只能访问
派生的
对象中受保护的基本成员。它无法访问(不一定)派生的对象中的成员。在失败的情况下,您试图通过<代码>基础和访问该成员,并且由于这可能是指一个不是“代码>派生< /COD>”的对象,所以不能访问。

< P>,尽管C++中的访问控制按类工作(与每个实例相反)。
protected
访问说明符有一些特性

语言规范希望确保您正在访问属于派生类的某个基子对象的受保护成员。您不应该能够访问一些基本类型的无关独立对象的受保护成员。特别是,您无法访问基础类型的独立对象的受保护成员。仅允许访问作为基础子对象嵌入到派生对象中的基础对象的受保护成员

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

这意味着在您的示例中,受保护的成员
somethingProtected()
不能通过
Base
对象、
Base*
指针或
Base&
引用访问,但可以通过
Derived
对象、
Derived*
指针和
Derived&
引用访问。您的普通
somethingProtected()
访问是允许的,因为它只是
this->somethingProtected()
的简写,其中
类型为
派生*

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

请注意,根据上述规则

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

第一个调用也会失败,而第二个调用会编译,即使两个都试图访问同一个实体。

C++中所做的是非法的。类的对象无法访问受保护的成员。只有成员函数才能访问受保护的成员<代码>受保护的成员的行为与私有成员类似,但由派生类继承时除外。考虑下面给出的程序,了解私有、公共和受保护成员之间的区别。< /P>
void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}
类基
{
私人:
void something private()
{

std::不能,但我可以这样做:'void something派生(派生&d)'compiles fine您正在访问一个公共方法,这很好。您也可以从main调用一些Dervied。请参阅我的编辑。不,他们访问一个基类的受保护方法。@juanchopanza不,他们正在访问另一个实例的基类方法的受保护方法。.不可能发生。.他们声称确实发生了。受保护的方法类似于私有的方法,它是不可能发生的o可以像私有方法一样被其他派生类使用,但您正试图像公共方法一样使用它。这并不能解释
void somethingDerived(derived&d)
标准中是否有相关的引用来描述这一点?@YoungJohn:11.4 Protected access*说当引用受保护的成员时“发生在某个C类的朋友或成员中”,并通过“一个(可能隐式的)对象表达式”发生,然后“对象表达式的类应为C或从C派生的类”"。在上述示例中,从
派生的
成员进行访问。在第一次访问中,对象expresson是
*b
,而在第二次访问中,对象expresson是
*this
。根据上述规则,第一次访问无效,第二次访问正常。关于私有访问的EDIT2如何?我的理解是->somethingProtected是SomethingObject->somethingProtected的一个特例,假设这是指向C类的指针,只要这个->somethingProtected有效,SomethingObject->somethingProtected也应该有效,前提是SomethingObject指向的类与C或从C派生的类相同。这正确吗?我理解规则。但是我不知道了解它存在的原因。调用其他基类型对象的受保护成员的危害在哪里?当使用虚拟函数时,这可能很有用。@Silicomancer,正如在本答案和本答案中所述,这是一种机制,用于确保不相关对象(例如从同一基派生的其他类型)的接口这在虚拟函数中如何有用?
void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}
class Base
{
    private:
    void somethingPrivate()
    {
        std::cout << "sasa" << std::endl;
    }
    public:
    void somethingPublic()
    {
        std::cout << "haha" << std::endl;
    }
    protected:
    void somethingProtected()
    {
        std::cout << "lala" << std::endl;
    }
};

class Derived : public Base
{
public:
    void somethingDerived()
    {
       Base b;
       b.somethingPublic();   // Works fine.
       somethingProtected();  // This is also fine because accessed by member function.
       //b.somethingProtected();  // Error. Called using object b.
       //somethingPrivate();      // Error. The function is not inherited by Derived.
    }
};