相互引用的 Const 对象
Const objects that refer to one another
作为帮助可视化问题的动机(否则只需跳到下面的代码),假设我正在编写一个纸牌游戏,其中某些牌"在玩"可以让你"购买"手中的其他牌。例如,假设你有一手牌,比如说四张牌,里面有一张王牌,你决定玩它。然后你得到另一手四张牌,现在王牌允许你免费玩一张女王牌。等等。
现在,我想编写这个游戏。我创建了一个Card
结构:
struct Card {
std::string name_;
Card(const std::string name) : name_{name} {}
std::string name() const { return name; }
};
const Card ace("ace");
const Card one("one");
// etc.
但后来我决定我不仅要记录一张卡的名称,还要记录它免费提供的卡以及免费提供这张卡的卡。像这样说:
struct Card {
std::string name_;
const Card* parent_; // card that gave this card for free
const Card* child_; // card that this card gives for free
Card(const std::string name) : name_{name} {}
std::string name() const { return name; }
std::string parent() const { return parent_->name(); }
std::string child() const { return child_->name(); }
};
(这段代码显然是零碎的,不是很健壮,但我只是想了解这个原则。为了添加父母/孩子,我还创建了以下方法:
struct Card {
// ...
private:
void set_parent(const Card* c) {
parent_ = c;
}
public:
void add_child(Card& c) {
child_ = &c;
c.set_parent(this);
}
// ...
};
现在,我可以像这样创建Card
对象:
Card ace("ace");
Card queen("queen");
// etc.
ace.add_child(queen);
// etc.
但是,我不得不牺牲Card
对象的恒定性。让我明确指出,这只是一个基本的例子。我打算编写的代码在其Card
类中有许多数据成员。因此,我想指出父/子卡而不明确复制数据。我也有很多"卡片",所以我宁愿不要复制尽可能多的数据。
我的问题是:我有什么办法将Card
对象保留为 const (因为它们永远不会包含变量数据)?还是我想错了?
可能与这个问题相关的是隐含的:这甚至重要吗?我是否有充分的实际理由希望这个功能常量对象在代码中作为常量?即使没有,那么即便如此,有没有办法让这些对象只是出于兴趣。
正如你所指出的,卡的数据(它的身份加上一些关于它的规则)是恒定的。 此外,它们在编译时是已知的。 所以:
#include <array>
enum class Rank {
None, Ace, Two, Three, Four // ...
};
struct Card
{
Rank rank = Rank::None;
std::array<Rank, 2> from = {};
std::array<Rank, 2> to = {};
};
constexpr Card cards[] = {
{},
{Rank::Ace, {Rank::Two, Rank::Three}, {}},
{Rank::Two, {}, {Rank::Ace}},
{Rank::Three, {Rank::Four}, {Rank::Ace, Rank::Four}},
{Rank::Four, {Rank::Three}},
};
您可以根据需要使数组尽可能大。 现在,您拥有了一整套在编译时已知的数据,并且存储紧凑。
如果不破坏正确构造它们的规则,就无法构造相互引用的const
对象。 但。。。。
您可以静态构造它们的读写,如private
、static
类成员,然后发布对它们的const
引用。 这将使对这些成员的访问权限成为只读的。
样本.h
class Sample {
const int priv_ro; /* this is true const field */
int priv_rw; /* this is read-write */
public:
const int& pub_ro_ro; /* read only alias */
const int& pub_rw_ro; /* idem */
//int& pub_ro_rw; /* error, cannot alias a const as read write */
int& pub_rw_rw; /* correct, public read write alias to private field */
static Sample global_rw; /* static global variable (read-write) */
static const Sample global_ro; /* static global variable (read-only) */
private:
Sample(int ro, int rw):
priv_ro(ro),
priv_rw(rw),
pub_ro_ro(this->priv_ro),
pub_rw_ro(this->priv_rw),
pub_rw_rw(this->priv_rw)
{
//priv_ro = ro; /* error, priv_ro is const */
priv_rw = rw; /* ok */
}
};
sample.cc
#include "sample.h"
Sample Sample::global_rw(8,3);
const Sample Sample::global_ro(5,2);
main.cc
#include <iostream>
#include "sample.h"
#define P(x) do{ std::cout << #x " = " << x << std::endl; } while(0)
int main()
{
P(Sample::global_rw.pub_ro_ro);
P(Sample::global_rw.pub_rw_ro);
P(Sample::global_rw.pub_rw_rw);
P(Sample::global_ro.pub_ro_ro);
P(Sample::global_ro.pub_rw_ro);
P(Sample::global_ro.pub_rw_rw);
// Sample::global_ro.pub_ro_ro = 0; /* cannot assign. */
// Sample::global_ro.pub_rw_ro = 0; /* cannot assign. */
// Sample::global_ro.pub_rw_rw = 0; /* cannot assign. */
// Sample::global_rw.pub_ro_ro = 0; /* cannot assign. */
// Sample::global_rw.pub_rw_ro = 0; /* cannot assign. */
Sample::global_rw.pub_rw_rw = 0;
P(Sample::global_rw.pub_ro_ro);
P(Sample::global_rw.pub_rw_ro);
P(Sample::global_rw.pub_rw_rw);
P(Sample::global_ro.pub_ro_ro);
P(Sample::global_ro.pub_rw_ro);
P(Sample::global_ro.pub_rw_rw);
}
生成文件
targets=sample
sample_objs=sample.o main.o
sample: $(sample_objs)
$(CXX) $(LDFLAGS) -o $@ $(sample_objs)
如果取消注释注释行,您将看到不可访问字段或const
定义错误。
- 被解释为低级别const的const对象的地址
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- "this"指向的对象是否与 const 对象相同?
- 从 const 对象访问非 const 方法
- 将非 const 对象用于 const 参数
- 如何键入用于const对象的自定义io操纵器
- 哪个 const 与哪个引用将更改参数并创建一个 const 对象?
- 无法在返回中转换 const 对象
- 接受对 const 对象的引用但没有 r 值的函数
- 当我调用 main 中使用 const 对象的 const 函数时,不断出现错误
- 在 const 对象上调用非 const 函数
- 正确的方法通过巨大的const对象的向量
- 如何重载 const 对象的 [],以便值赋值不会导致编译错误
- 相互引用的 Const 对象
- 析构函数是否可以在 const 对象上调用非 const 函数
- decltype 不会推断 const 对象的 const 成员
- 防止const函数被调用非const对象
- constexpr引用非const对象