【问题标题】:Why does the first statement here not violate protected access while the second one does?为什么这里的第一个语句不违反受保护的访问,而第二个语句呢?
【发布时间】:2013-05-02 02:46:19
【问题描述】:

我正在研究这段代码:

#include <iostream>

class A
{
public:
    A() {};

    void fox(A& otherA) { otherA.hello(); }

protected:
    void hello() {std::cout << "hello" << std::endl;}
};

A a1,a2;

int main(void)
{
    a1.fox(a2);
    a1.hello();
}

对于说a1.fox(a2) 将如何编译而说a1.hello() 不会编译,我有点困惑。我会假设它会中断,因为虽然我可以从类中调用受保护的和私有的函数......允许我在 otherA 对象上执行此操作意味着我必须知道我是从成员中调用它它自己的类。为什么/如何工作?

【问题讨论】:

标签: c++ protected


【解决方案1】:

Protected 不是逐实例访问控制,而是逐类访问控制。

main()(不在任何类中)根本无法调用任何类的私有或受保护方法;因此它无法调用a1.hello()

另一方面,A::fox(A&amp;) 的实现位于类 A 内部,因此它可以在自身和类的其他实例上调用其私有和受保护的方法。

【讨论】:

    【解决方案2】:

    因为A 正在调用otherA.hello();。你不能直接调用privateprotected代码,但是A的后代,包括A本身,可以调用A(后代不能访问Aprivate数据/方法,但A 可以访问Aprivate 数据/方法)。相关地,A 也可以访问A 的其他实例的private 数据/方法(这通常是复制构造函数和赋值运算符的工作方式)。

    事实上,正是在class 中使用protected 代码的能力可以创建一些非常强大的OO 概念。话虽如此,我认为即使在可能的情况下调用内部对象的 privateprotected 方法也是一种滥用,但希望直接对自己使用它们是设计而不是方便。

    在 C++ 中,您可以通过将项目标记为 virtual 而不提供实现来提供classes(或structs)的抽象实现。

    class A
    {
    public:
        void set_value(const std::string &value)
        {
            if (is_valid(value))
            {
                this->value = value;
            }
        }
    
        const std::string &get_value() const
        {
            return value;
        }
    protected:
        virtual boolean is_valid(const std::string &value) const = 0;
    private:
        std::string value;
    }
    

    然后

    class B : public A
    {
    protected:
        virtual boolean is_valid(const std::string &value) const
        {
            return value != "abc";
        }
    }
    

    请注意,A 被设置为继承功能,并且它被构建为预期它被提供(假设上面的示例并没有真正提供很多实用程序,但它确实说明了我的意思)。

    【讨论】:

      【解决方案3】:

      C++ 中的访问控制处于类级别。不是实例级别。

      编译器不可能知道otherA 是否实际上是同一个实例。您需要运行时支持来实际确定实例的身份以提供此类访问控制。

      除了这带来的性能问题外,C++ 的目标是在编译时捕获错误,而不是在执行时捕获错误。正如 stroustrup 所说,数据封装和类型安全功能无法防止某人进行欺诈(当程序可以无中介地访问所有分配的内存时)。

      现在,为什么可以在没有运行时检查的情况下满足于解决方案。类比可能会有所帮助——因为作为一个类的实现者,你不会抢劫自己的房子。

      【讨论】:

        猜你喜欢
        • 2020-10-06
        • 2015-12-31
        • 1970-01-01
        • 1970-01-01
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-04
        相关资源
        最近更新 更多