子类中的成员是对父成员的引用
Member in child class a reference to parent member?
假设我有以下测试代码:
#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
,和衍生类Vector2
, Vector3
和Vector4
;我想修改VectorN
中的data
成员,使用x
, y
, z
或r
, g
, b
等子类中的成员。
为什么可以通过子类中的引用成员修改数据成员,而不是直接修改?
因为你没有修改引用。c++中的const
不是逻辑const
,它更像是位const
。当你这样做的时候:
w.x = 100;
你实际上没有修改w.x
,所以这是允许的。x
恰好引用了const
对象的不同数据成员,这意味着这是未定义的行为。但这是完全合法的法典。你不应该这么做。
还有,有没有更好的方法来实现这个行为?
如果你想修改const
对象上的成员,就把它们设为mutable
。
将w
声明为const
。const
不适用于被引用的成员(如果是指针,则是指针)。
对于引用来说,这一点就不那么清楚了,因为float& const
是不允许的,因为你不能重新分配引用(所以你可以认为它是默认的& const
)。
但是有了指针就更容易理解了:
const float *x
这是指向常量float
的指针。不能通过解引用的方式给指向的对象赋新值。
float* const y
这是指向float
的常量指针。可以通过解引用给指针赋一个新值,但不能给指针赋一个新值(让它指向别的东西)。
现在声明const Weird3 w
使所有字段在w中不可重新分配(前面示例中的float* const
),但是允许修改它们的值。这意味着你实际上并没有改变w
的状态,而是改变了w
引用或指向的东西。
为什么可以通过子类中的引用成员修改数据成员,而不是直接修改?
为什么它不能直接工作是很明显的,你试图修改const对象。它允许你修改引用的原因也很明显——你不是在修改对象的状态,而是在修改引用指向的其他东西。引用指向const对象本身或其他对象的事实在这里是不可见的(对于编译器来说),它应该只是防止将const对象赋值给左值引用。
那么问题是为什么你能够将const对象的成员赋值给左值引用。答案是——对象的常量在构造函数中是不可见的。它可能会在未来的语言变化中得到改进,但它现在是这样工作的。
无论如何修改const对象导致UB,所以你的评论"工作正常"是一个错觉。
还有,有没有更好的方法来实现这个行为?
"更好"的方法是直接使用const_cast<>
。它至少是显式的,并且可以用来移除原本是非const的对象的const,但是通过修改获得了它。同样,您不应该通过"hack"修改const对象,也不应该使用C强制转换或const_cast<>
,因为它会导致UB。
- 非静态成员引用必须相对于特定对象
- 在C++中,如果成员引用在其声明中初始化,为什么需要存储空间?
- 成员引用基类型 'char' 不是 C++ 中的结构或联合
- 对静态分配的子类对象进行静态分配的纯虚拟父类引用是否合法?
- 成员引用基类型不是结构或联合
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 成员引用基类型 'double [10]' 不是结构或联合
- 使用默认值初始化成员引用
- 错误:成员引用基类型"uint32_t"(也称为"无符号 INT")不是结构或联合
- 无法用2D矢量成员引用对象
- 是否可以在同一对象中对成员 std::shared_ptr 进行成员引用<variable>?
- 是否有一种方法可以将C 类成员引用到向量而不明确添加它们
- C++:成员引用还是指针
- C++非静态成员引用
- C++ 成员引用基类型'int'不是结构或联合
- 将成员引用变量置于成员指针变量之上的原因
- C++非静态成员引用必须相对于特定对象
- 是否可以派生使父成员可变
- 无法理解错误 msg:"非静态成员引用必须相对于特定对象"
- 子类中的成员是对父成员的引用