2

我正在研究这段代码:

#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对象上这样做意味着我必须知道我是从它自己的成员中调用它班级。为什么/如何工作?

4

3 回答 3

6

受保护的不是逐个实例的访问控制,而是逐类的访问控制。

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

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

于 2013-05-02T02:50:22.323 回答
0

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

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

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

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是为了继承功能而设置的,并且它是为了预期它被提供而构建的(假设上面的示例并没有真正提供很多实用程序,但它确实说明了我的意思)。

于 2013-05-02T02:49:52.073 回答
0

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

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

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

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

于 2013-05-02T09:14:47.323 回答