结构或类以及公共数据呢?

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++ 中,structclass 除了访问控制之外是相同的。所以结构对成员和继承的默认访问是公共的,而类是私有的。所以你可以给你的结构一个默认的构造函数和其他人来初始化它。

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_remainingtime_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++ 中的 visibilityaccessibility 是有区别的。你应该写的是,accessibilitynot visibility.

以上是关于结构或类以及公共数据呢?的主要内容,如果未能解决你的问题,请参考以下文章

结构或类中的数组初始化

此特定案例的结构或类[重复]

在结构或类中使用智能指针

PHP的SPL扩展库数据结构

数据结构—前缀树Trie的实现原理以及Java代码的实现

数据结构之字典树