子类成员对父成员的引用?

时间:2015-07-24 02:47:43

标签: c++ templates reference polymorphism

说我有以下测试代码:

#include <iostream>
using namespace std;

class Vector3 {
public:
    float data[3];
};

class Weird3 : public Vector3 {
public:
    union {
        struct { float &x, &y, &z; };
        struct { float &r, &g, &b; };
    };

    Weird3() : x(Vector3::data[0]), y(Vector3::data[1]), z(Vector3::data[2]) {}

};

int main(int argc, char** argv) {

    const Weird3 w;

    w.x = 100; // Works ok!
    cout << w.x << endl;

    w.data[0] = 100; // Error: assignment of read-only location
    cout << w.x << endl;

    return 0;
}

为什么通过子类中的引用成员修改data成员有效,但不能直接?另外,有没有更好的方法来实现这种行为?例如,我有一个模板类VectorN,派生类Vector2Vector3Vector4;我想使用dataVectorNxy,{{等子类中的成员修改z中的r成员1}},g

3 个答案:

答案 0 :(得分:2)

  

为什么通过子类中的引用成员修改数据成员有效,但不能直接?

因为您没有修改参考。 C ++中的const不是逻辑const,它更像是按位const。当你这样做时:

w.x = 100;

您实际上并未修改w.x,因此允许这样做。 x碰巧引用const对象的不同数据成员的事实意味着这是未定义的行为。但它是完全合法的代码。你不应该这样做。

  

另外,有没有更好的方法来实现这种行为?

如果您希望能够修改const对象上的成员,只需将它们设为mutable即可。

答案 1 :(得分:1)

w被声明为constconst不适用于引用的成员(或指针时的指针)。

由于不允许使用float& const,因此引用不太明确,因为您无法重新分配引用(因此默认情况下您可以将其视为& const。)

但是指针更清楚易懂:

const float *x

这是一个指向常量float的指针。您无法通过解除引用来为指定的值分配新值。

float* const y

这是指向float的常量指针。您可以通过取消引用来为指针指定一个新值,但是您不能为指针指定一个新值(使其指向其他指针)。

现在声明const Weird3 w使得所有字段在w(前一个示例的float* const)中不可重新分配,但您可以修改它们的值。这意味着您实际上并未改变w的状态,而是更改w引用或指向的内容。

答案 2 :(得分:0)

  

为什么通过子类中的引用成员修改数据成员有效,但不是直接?

为什么它不直接工作很明显,你尝试修改const对象。为什么它允许你修改引用也很明显 - 你不是修改对象的状态,而是修改其他引用指向的其他内容。引用指向const对象本身或其他东西的事实在这里是不可见的(对于编译器)而且它不可能,它应该只阻止将const对象分配给左值引用。

所以问题是为什么你能够将const对象的成员分配给左值引用。答案是 - 对象的constness在构造函数中不可见。它可能会通过将来改变语言来改进,但现在就可以这样做了。

无论如何修改const对象会导致UB,所以你的评论&#34;工作正常&#34;是一种幻觉。

  

另外,有没有更好的方法来实现这种行为?

&#34;更好的&#34;方法是直接使用const_cast<>。它至少是显式的,可以用来删除最初非const的对象的常量,但是通过修改得到它。再次,您不应该通过&#34; hack&#34;修改const对象。也不使用C cast或const_cast<>,因为它会导致UB。