c++只允许成员变量被设置一次
C++ Only Allow a member variable to be set once
我接触c++已经有一段时间了,但我想确保我在做的时候坚持最佳实践,包括const正确。
我目前正在为游戏框架构建一个代码库,我有以下类(简单总结):
class Screen
{
public:
Clear();
}
和
class Game
{
private:
Screen* screen;
protected:
const Screen* GetScreen() const;
}
为简洁起见,我省略了其余部分,但可以这么说,Game
类负责创建Screen
类实例。创建后,只能通过GetScreen()
方法访问。
我的想法是,当创建一个新游戏时,我将继承这个基类,所以作为一个例子,在渲染循环期间,我想要清除屏幕以重新绘制下一帧。现在,在我上面的定义中,在使用GetScreen()
方法时不允许调用Clear()
方法,因为它不是const
。clear方法实际上会改变类的内部工作(通过清除先前显示的图像这一事实),因此我将const
声明排除在定义之外。如果我使它成为const
,那么我将不得不拥有Screen
类的一些内部工作方式作为mutable
,但从我所读到的,这将不是非常const正确的。
所以,我的问题有两个部分。我是否应该将void Clear()
更改为void Clear() const
,并将内部工作部分更改为mutable
?
或者是另一种选择,允许我使Game
类的screen
成员只能由Game
类设置一次,以便我可以在程序运行时的其余时间访问非const成员函数。
谢谢你的帮助。
由于Game::screen
是私有的,它不能被派生类访问。虽然GetScreen()
的调用者可以访问Screen
对象,但他不能修改Game
中存储的screen
指向的对象。因此,您完全可以提供以下两个重载:
class Game
{
Screen *screen;
protected:
const Screen* GetScreen() const;
Screen* GetScreen();
};
它们都不允许派生类修改screen
指针本身,所以它不能"重置"它指向Game
不希望它指向的地方。
'const'的概念用于表明对象的内部状态不应该被修改。
void f(const Object& o)
{
// 'o' cannot be modified
}
将非静态成员标记为const
的能力允许您强制const
引用的对象的持有者不能修改内部状态。例如,在下面的场景中,Object
有一个访问器str
,它返回对内部状态的引用,该内部状态同时具有非const和const重载:
struct Object
{
// non-const: caller can modify internal state
std::string& str();
// const: caller cannot modify internal state
const std::string& str() const;
};
非const重载允许修改内部状态,但只能在对对象的非const引用上调用;const重载不允许修改内部状态,可用于const和非const对象引用。
在您展示的场景中,Game
似乎是一个包含程序中所有内容的整体单例对象。如果是这样,那么将引用传递给Game
(或从它派生的对象)是否有用似乎是值得怀疑的,这使得const Game&
和Game&
之间的区别变得有些没有意义。如果是这种情况,那么const-正确性就没有任何用处,如果您简单地将Game
的所有成员都设置为非const,则可以避免您自己的头痛。
我强烈建议你更新一下c++中指针的知识。现在几乎没有理由使用原始指针了。
直接回答这个问题,Game.GetScreen()
函数想要'const'的方式不同,这取决于你希望它如何表现。
如果你返回一个const Screen*
,你返回一个指向Screen对象的指针,这个对象是常量(不能被修改)。通常情况下,你会希望将这样一个函数设置为const,允许它在一个自身为const的游戏对象上被调用。如果某人拥有非const Game对象,你可以允许他们获得Screen对象,然后通过返回Screen*
进行修改。
这就是说,我回到我开始的观点,你不应该使用原始指针。
最初,您应该只按值存储Screen对象,并返回引用,为您提供如下行:
Class Game{
Screen screen;
public:
const Screen& GetScreen() const{ return screen; }
Screen& GetScreen(){ return screen; }
};
这看起来像是复制Screen对象来返回它,但是返回类型确保您返回的是对相同Screen对象的引用,而不是副本。
如果你真的需要动态创建Screen对象(即,你不能在创建Game对象之前或在创建Game对象时创建它),那么你应该使用std::unique_ptr<Screen>
。这可以像原始指针一样使用,但会为您处理很多功能。但是,您希望共享对这个Screen指针的访问,因此您可能希望使用std::shared_ptr<Screen>
并从get函数返回std::weak_ptr<Screen>
。weak_ptr可以用来允许其他人访问,但是你的初始Game对象仍然拥有Screen对象。
长话短说,按值存储Screen对象,并返回对它的引用。
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在C++中一次将矢量值写入多个文件
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么 zlib 放气初始化调用一次不起作用?
- 在一次迭代中从 txt 文件中读取多行
- 为什么无论你输入什么,这"while(cin.get(str,3))"只运行一次?
- 在头文件和 cpp 文件中使用一次 #pragma 时出现结构重定义错误
- 如何仅使用一次固定<<设置精度(2)?或者至少恢复到默认行为?
- 仅在函数中设置静态变量一次
- 只设置一次方法中变量的值
- cppUnit:针对多个测试方法执行一次的设置函数
- 确保静态成员最多设置一次 (C++)
- 在一个位集中一次设置多个位
- 映射和设置总是一次分配一个项目吗
- 将CMAKE_CXX_FLAG设置在父目录中一次,并在子目录中有效
- 设置数组一次索引很多?复合文字
- 是否可以创建一个类似C的字符串(char*)数据只能设置一次的结构
- c++只允许成员变量被设置一次
- 是否有一种方法可以在一次拍摄中设置每个字段的宽度,而不是每次使用流媒体设置