【问题标题】:Should you have a getter function for class array?你应该有一个类数组的getter函数吗?
【发布时间】:2021-04-23 01:44:56
【问题描述】:

我正在学习 C++,并且有一个与类和模板相关的问题。 我知道为班级中的每个变量设置“getter”和“setter”函数是一种很好的做法。但是使用下面显示的代码,您是否应该为数组提供“getter”函数?理论上,打印函数的作用与“getter”函数的作用相同——打印出数组中的所有内容。如果需要,返回该数组的正确代码是什么?该数组是一个类对象数组。

到目前为止我的想法和代码:
queue.h

#pragma once


template<class T>
class Queue {
    public:
        Queue(int = 1);
        ~Queue();
        void setQueue(int);
        void enqueue(T);
        void dequeue();
        const T* getQueueArray() const;
        const int getArraySize() const;
        const int getArrayIndex() const;
        void printQueue();
    
    private:
        T* queueArray;
        int arraySize, arrayIndex;
};

queue.cpp

#include <iostream>
#include "queue.h"


template<class T>
Queue<T>::Queue(int arraySize) {
    this->setQueue(arraySize);
}


template<class T>
Queue<T>::~Queue() {
    delete [] this->queueArray;
}


template<class T>
void Queue<T>::setQueue(int arraySize) {
    this->arraySize = arraySize;
    delete [] this->queueArray;
    this->queueArray = new T[arraySize];
    this->arrayIndex = 0;
}


template<class T>
void Queue<T>::enqueue(T object) {
    if (this->arrayIndex == this->arraySize) {
        std::cout << "Rinda ir pilna, nevar pievienot elementu!\n";
    }
    
    else {
        this->queueArray[this->arrayIndex] = object;
        this->arrayIndex++;
    }
}


template<class T>
void Queue<T>::dequeue() {
    if (this->arrayIndex == 0) {
        std::cout << "Rinda ir tuksa!\n";
    }

    else {
        for (int i = 0; i < this->arraySize - 1; i++) {
            this->queueArray[i] = this->queueArray[i + 1];
        }

        this->arrayIndex--;
    }
}


template<class T>
const T* Queue<T>::getQueueArray() const {
    return this->queueArray;
}


template<class T>
const int Queue<T>::getArraySize() const {
    return this->arraySize;
}


template<class T>
const int Queue<T>::getArrayIndex() const {
    return this->arrayIndex;
}


template<class T>
void Queue<T>::printQueue() {
    for (int i = 0; i < this->arrayIndex; i++) {
        std::cout << i + 1 << ". ";
        this->queueArray[i].printHuman();
    }
}

数组 getter 函数工作并返回一个内存地址。这种行为正确吗?

我想问另一个问题,关于类打印功能,这将是更好的 2:
std::cout &lt;&lt; "something something" &lt;&lt; classVariable; 要么 std::cout &lt;&lt; "something something" &lt;&lt; getClassVariable(); 一种方法是直接访问变量,另一种方法是使用“getter”函数。使用类似的功能是否会显着影响性能?

【问题讨论】:

  • 值得一读,因为你的代码不会这样编译:Why can templates only be implemented in the header file?
  • “我知道这是好的做法”应该是“我知道这是不好的做法”。 Getter 和/或 setter 仅在必要时使用。
  • #include "queue.cpp" 不要那样做。
  • getter 和 setter 方法允许通过接口访问。他们隐藏了实现。例如,可以将它们更改为计算值而不破坏接口,而不是返回硬编码值。直接访问使得耦合更紧密,增加了模块之间的依赖关系。
  • 您希望为实际上属于该类的公共可用 API 的内容而不是不属于该类的内容提供 getter。你正在写一个队列,而不是一个数组。这意味着您可以通过 topfront 方法访问,而不是通过将原始指针传递给内部存储表示。

标签: c++ arrays class templates return


【解决方案1】:

这篇文章主要基于观点,但我将提供我的观点。您收到了 cmets 告诉您一些事情。

首先,我鼓励您以“C++ 方式”做事。模板在标题中完成,“#include”queue.cpp“真的很恶心。但我至少理解一个可能没问题的例子,因为它可以让你专注于实现整个模板的所有代码之外的其他事情. 只是不要在实践中这样做。

至于 getter 和 setter——我不同意你得到的一些 cmets。我绝对不会在内部结构上设置 setter,但如果这是一个严肃的课程,我绝对会实施某种方法来检查全部内容。

毕竟,想象一下,有人希望能够计算队列中有多少元素满足了特定的约束。您不想尝试预测某人可能想做的任何事情。但是您当然可以通过能够获取当前队列(const)或通过迭代器来检查内容的一些方法。迭代器更难实现,但它们适合许多其他算法。查看#include 的全部内容。

所以:

  1. 在某种访问系统(getter / iterator)上是的
  2. 二传手没有

除此之外,我不确定为什么您的示例代码不愿意在必要时增加列表,但如果它不愿意,它应该以某种方式向调用者表明它未能正确排队。

【讨论】:

    【解决方案2】:

    首先对于模板类,在头文件中声明并在源文件中进行定义是行不通的。所以试着把它们放在同一个头文件中。

    我知道为你的类中的每个变量都有一个“getter”和一个“setter”函数是个好习惯

    是的,但并非总是如此。例如,在将数据复制到缓冲区时,获取实际的数据指针会有所帮助。设置通常由赋值运算符完成,

    Value& operator=(const Object& other) { ... } // Copy assign operator.
    Value& operator=(Object&& other) { ... } // Move assign operator.
    

    所以我建议不要在这些类型的对象中使用 setter。

    我想问另一个问题,对于类打印功能,这将是 2 中更好的: std::cout

    这是基于意见的,通常您通过重载 &lt;&lt; 运算符将内容打印到控制台,

    template<class T>
    ostream& operator<<(ostream& os, const Queue<T>& dt)
    {
        os << /* print content */;
        return os;
    }
    
    int main()
    {
        Queue<int> queue;
        std::cout << "Printing queue! " << queue;
    }
    

    一种方法是直接访问变量,另一种是使用“getter”函数。它是否重要,并且使用类似的功能会显着影响性能

    不,他们不会。如果你内联函数,就不会有性能差异。并确保启用优化,否则额外的调试信息会减慢它的速度。我认为使用 getter 函数会更安全。

    【讨论】:

    • 是的,但并非总是如此。 误导。默认值应该是无访问器。访问器削弱了封装,只是不如直接public 访问。更喜欢对对象执行某些操作的函数,而不是直接设置成员或获取成员并在对象外部对其值进行操作。
    猜你喜欢
    • 2014-02-07
    • 2010-09-26
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多