结构或类以及公共数据呢?
Posted
技术标签:
【中文标题】结构或类以及公共数据呢?【英文标题】:struct or class and what about public data? 【发布时间】:2012-04-20 05:35:11 【问题描述】:在创建类时,我被告知没有公共数据成员。没关系,我明白为什么,但这是我的问题。我有一个在类中使用的结构(线性链表)。我真的很想将其中一个结构字段(一个数组)初始化为 NULL,以便我可以检查客户端是否传递给我有效的结构,而不是未初始化的充满垃圾值的结构。我意识到 C++ 不允许我在 struct 声明中设置默认值,那么如何防止客户端给我垃圾?
struct task
char *description;
char *name;
float time_remaining;
float time_spent;
;
然后在我的课堂上,我正在尝试做类似的事情:
//I am making a copy of "to_add" and storing it in the LLL
int list::add_to_list(const task & to_add)
/.../
我不希望用户将一堆未初始化的“任务”添加到链接列表中......该怎么办?当我将该结构转换为一个类并将数据成员移动到私有时,我在尝试访问数据成员以复制它们时遇到了很多问题。我非常小心地不做任何事情来影响 var 的值,但我无法摆脱编译器给我关于“错误:将 'const task' 作为 'char* task::get_comp_name 的 'this' 参数传递”的错误()' 丢弃限定符 [-fpermissive]" ("get_comp_name") 是我确定没有编辑任何值的 getter 之一,只是传递给我一份副本)在我开枪之前请帮助我。在脸上。
【问题讨论】:
我无法理解问题所在。没有公共数据成员意味着访问“外部”世界可能“有趣”的数据的唯一方法是通过 getter,如果需要设置它们,则必须通过 setter 进行。创建实例后,您可以将私有成员初始化为您想要的任何内容。从外部作为方法参数传递的任何东西都可能是不安全的,但这是“正常的”,我看不出你是如何将它与不公开数据的要求结合起来的,在我看来它们是两个不同的“事实”。你能解释清楚吗? 错误是因为你没有声明函数const
。如果你真的想提供访问器而不是公共数据,那么 getter 应该类似于char const * get_comp_name() const;
。
【参考方案1】:
在 C++ 中,struct
和 class
除了访问控制之外是相同的。所以结构对成员和继承的默认访问是公共的,而类是私有的。所以你可以给你的结构一个默认的构造函数和其他人来初始化它。
struct task
task() : desctiption(0), name(0), time_remaining(0.), time_spent(0.)
char *description;
char *name;
float time_remaining;
float time_spent;
;
添加构造函数的一个副作用是结构不再是聚合。这对您来说可能是也可能不是问题。
在 C++11 中,您还可以在声明时初始化成员:
struct task
char *descriptionnullptr;
char *namenullptr;
float time_remaining0;
float time_spent0;
;
这种就地初始化也接受type x = y
语法,并且无参数 初始化导致值初始化,这导致原始类型零初始化 ,因此示例中的参数可以省略。
【讨论】:
+1。顺便说一句,char *name
就足够了。同样,float time_spent
。 More here.
@Nawaz 确实,我会添加一些东西。
就是这样!!!该死的我爱你们。这里有很多聪明人。非常感谢!【参考方案2】:
这里有几个问题。
公开还是不公开?
公共属性看起来很方便,但它们通常会在你最意想不到的时候回来咬你。我已经怀疑time_remaining
和time_spent
存在问题:我想它们是同时修改的,不是吗?
默认情况下,变量属性应该是private
,以便类可以强制不变量,例如time_remaining + time_spent
在任务的整个生命周期中都是一个常量。
常量属性可以是public
,它们在不变量中的作用无论如何都在构造函数中一劳永逸地解决了。
但是奇怪的错误信息?
这是因为您缺少好的教程或书籍。手头的问题很简单:这是一个与const
-ness 相关的问题。
const
对象只能通过 const 引用或值传递给函数/方法,并且只能在其上调用 const
方法。在您的情况下,name()
方法的正确声明应该在方法名称后有一个 const
限定符。
总而言之
并输入std::string
,因为它更容易操作。
class Task
public:
Task(): time_remaining(0), time_spent(0)
Task(std::string name, std::string desc, float duration):
_name(name), _desc(desc), _time_remaining(duration), _time_spent(0)
// Accessors
std::string const& name() const return _name;
std::string const& description() const return _desc;
float time_remaining() const return _time_remaining;
float time_spent() const return _time_spent;
// Modifiers
void spend(float duration)
_time_remaining -= duration;
_time_spent += duration;
private:
std::string _name, _desc;
float _time_remaining, _time_spent;
; // class Task
注意:检查传递给spend
方法的duration
是否优于_time_remaining
属性可能是有益的,否则您花费的比您拥有的多...
【讨论】:
这看起来是一个很棒的宣言!所以说重点。就访问器而言:因为您使用的是字符串,所以这些访问器只是返回一个副本,对吗?如果您正在使用数组(即指针)怎么办?函数名后的“const”是否足以让一个人访问/制作数组的独立副本? @MCP:不,他们返回的是std::string const&
,这是对字符串的常量引用。如果调用者写std::string const& name = t.name();
,她得到一个常量引用,如果她写std::string const name = t.name();
(&
的细微缺失),她得到一个const
值(不是const
在后一种情况下是可选的)。方法上的const
意味着您无法更改类内部属性。如果类持有一个指针,那么指针本身不能改变,但它指向的对象如果不是const
-qualified,则可能会改变。
@MCP:您应该在本网站或教程上查找问题以了解 const
-ness。如果解释得当,这是一个简单的话题,但如果解释得当,它可能会完全令人困惑。特别是因为它不仅是技术性的,还可以用于逻辑const
-ness,通常更有用,这需要一些概念方面的经验(以及入门指南)。
我会这样做的。这是我第一次真正开始编写可以从 const-ness 中受益的东西……虽然我正在为你们学习,但我绝对不太明白它是如何工作的。我去找教程。谢谢!【参考方案3】:
为结构实现构造函数:
struct task
task() : description(0), name(0), time_remaining(0), time_spent(0)
char *description;
char *name;
float time_remaining;
float time_spent;
;
C++ 中类和结构的唯一区别是其成员的默认可访问性。
【讨论】:
另一个区别是默认继承,对于struct是public,对于class是private。 @Andreas:C++ 中的 visibility 和 accessibility 是有区别的。你应该写的是,accessibility,not visibility.以上是关于结构或类以及公共数据呢?的主要内容,如果未能解决你的问题,请参考以下文章