【问题标题】:Can an object's member function modify another object?一个对象的成员函数可以修改另一个对象吗?
【发布时间】:2019-01-07 03:51:58
【问题描述】:

今天的问题是,一个对象可以修改另一个相同类类型的对象吗?例如,假设一个类有一些私有数据成员。我们创建了该类类型的两个对象。一个对象如何修改另一个对象?这样做合法吗?

我们能否编写一个成员函数,让一个对象能够修改另一个相同类类型的对象?如果一个对象代表电子游戏中的一名战士,并且您想让一名战士能够伤害另一名战士,这可能会很有用。

事实证明,在 C++ 中可以做到这一点。我们想了解为什么 C++ 赋予我们这样做的能力。这样做,我们必须首先了解成员函数实际上是什么以及它是如何工作的。阅读问题的答案。

【问题讨论】:

    标签: c++ member-functions this-pointer


    【解决方案1】:

    这里我们有一个class Bucket 有两个私有数据成员。还有构造函数、复制构造函数和其他一些函数。让我们把注意力转向modifyOther 函数。它接受一个参数,即指向Bucket 对象的指针。然后该成员函数可以编辑其他 Bucket 对象。

    #include <iostream>
    using namespace std;
    
    class Bucket {
      public:
        // Acts as constructor acceptint two arguments x and y,
        // one argument x,
        // or no arguments (default constructor).
        Bucket(int x = 0, int y = 0) : x(x), y(y) {}
    
        Bucket(const Bucket& rhs)
        {
            this->x = rhs.x;
            this->y = rhs.y;
        }
    
        void modifyOther(Bucket* other)
        {
            other->x = -1;
            other->y = 1;
        }
    
        void printInfo()
        {
            cout << "x = " << this->x << endl;
            cout << "y = " << this->y << endl;
            cout << endl;
        }
      private:
        int x;
        int y;
    };
    
    
    int main()
    {
        Bucket a(10, 5);
        a.printInfo();
    
        Bucket b(8, 9);
        b.printInfo();
    
        a.modifyOther(&b);
    
        a.printInfo();
        b.printInfo();
    
        return 0;
    }
    

    main() 函数中,我们声明了两个class Base 类型的对象。请注意,它们是相同的数据类型。这很重要。然后我们调用对象amodifyOther函数成功修改对象b的内部私有数据成员。

    这是这段代码的输出:

    x = 10
    y = 5
    
    x = 8
    y = 9
    
    x = 10
    y = 5
    
    x = -1
    y = 1
    

    现在您可能会想,这不应该是非法的吗?私有数据成员不是只允许对象本身访问吗?事实证明,privatepublic 这样的成员访问说明符是由编译器强制执行的,编译器没有单个对象的概念,只有类。

    private 数据成员被允许被其类内的任何东西访问,被允许被类的成员函数访问。由于modifyOtherclass Base 类型的成员函数,它可以访问private 变量int xint y 并更改它们。因此,这里没有违反任何规则。

    什么是成员函数?它只是一个独立的函数,它接受一个指向调用对象的“不可见”指针,并通过该指针访问该对象。该指针称为this。查看printInfo 函数。我使用this-&gt;y 表示成员变量是有原因的。因为所有成员函数都采用一个“不可见的”this 指向调用对象的指针,所以函数实际上看起来像:

    void printInfo(Bucket* this)
    {
        cout << "x = " << this->x << endl;
        cout << "y = " << this->y << endl;
        cout << endl;
        // this->x = -1;
    }
    

    请注意,我故意在此函数中添加了最后一行。将printInfo 函数的定义与modifyOther 函数的定义进行比较。它们看起来非常相似。事实上,唯一的区别是Bucket* 参数的名称! Bucket* this 是指向调用对象的隐式指针。 Bucket* other 只是一个指向其他 Bucket 对象的指针。编译器是“愚蠢的”,它无法仅根据它们的名称来区分这两个Bucket *s。它对他们一视同仁!因此我们可以得出结论,用于修改调用对象的相同机制也可以用于修改相同类类型的另一个对象。

    请记住,我们不能使用相同的技巧将指针传递给 另一个 类类型的对象并对其进行修改。这是行不通的。成员函数只能访问在同一类中的变量private 表示该变量只能由该特定类的成员函数修改,不能由任何其他类修改。一个priavte变量不能被外界修改,所以外界也包含了不同类的任何成员函数。

    如果你不理解这个话题,请看我在 StackOverflow 上的类似问题,也请观看我在研究这个话题时发现的这个 YouTube 视频。

    Are there multiple member functions compiled for each C++ object?

    What is the 'this' pointer?

    https://www.youtube.com/watch?v=_Wv-lEl1sgg&t=0s

    【讨论】:

    • 这个答案听起来像是编译器的一个缺点,如果语言能阻止相同类型的对象相互访问可能会更好。但它实际上是一种有意的语言功能。没有它,即使是常见的东西,比如复制/移动构造函数、赋值运算符、比较运算符和交换函数,也会很烦人。
    • C++ 语言和编译器当然可以将通过 this 的访问(显式或隐式)区别于其他成员访问 - 事实上,在某些情况下使用 protected 成员确实有所不同.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 2013-02-03
    • 1970-01-01
    • 2013-03-12
    相关资源
    最近更新 更多