未完全封装的私有类成员

Private class members not fully encapsulated?

本文关键字:成员 封装      更新时间:2023-10-16

这是c++实例级封装的后续文章。

我已经定义了一个类,并从这个类创建了两个对象。

#include <iostream>
#include <ctime>
#include <string>
using namespace std;
class timeclass {
  private:
  string date;
  time_t gmrawtime, rawtime;
  struct tm * timeinfo;
  char file_date[9];
  void tm_init(int);
public:
  timeclass(int);
  void print_date();
};
void timeclass::tm_init(int y) {
  timeinfo = gmtime(&rawtime);
  timeinfo->tm_year = y - 1900; // timeinfo->tm_year holds number of years since 1900
  timeinfo->tm_mon = 0;
  timeinfo->tm_mday = 1;
  timeinfo->tm_hour = 0;
  timeinfo->tm_min= 0;
  timeinfo->tm_sec= 0;
}
timeclass::timeclass(int y) {
  timeclass::tm_init(y);
  gmrawtime = mktime(timeinfo) - timezone; 
}
void timeclass::print_date() {
  strftime(file_date,9,"%Y%m%d",timeinfo);
  date = string(file_date);
  cout<<date<<endl;
}
/* -----------------------------------------------------------------------*/
int main()
{
  timeclass time1(1991); 
  timeclass time2(1992); 
  time1.print_date(); // Prints 19920101, despite being initialized with 1991
  time2.print_date(); // Prints 19920101, as expected
  return 0;
}

这个例子是从我的主程序中分割出来的日期计数器的一部分,但它说明了我的观点。我想为类(time1和time2)的每个实例运行一个日期计数器,但是一旦构造了time2对象,我认为封装在time1中的'timeinfo'变量就会被time2构造函数覆盖。

我知道c++只支持类级封装,我想知道我的问题是因为同一个类的成员可以访问彼此的私有成员。有没有什么办法,能让我实现我想做的事?谢谢你!泰勒

gmtime(), localtime(), ctime()asctime()返回指向静态数据的指针。因此,后续调用可能会覆盖之前调用所写的信息。这也意味着这些调用不是线程安全的,尽管在这种情况下不涉及多个线程。

对于这个限制,其他答案提供了可能的解决方法。

您实际上并不需要gmtime()(参见Shafik的答案)。你只是想要一个std::tm,你可以修改:

void timeclass::tm_init(int y) {
  timeinfo = new std::tm;
  timeinfo->tm_year = y - 1900;
  timeinfo->tm_mon = 0;
  timeinfo->tm_mday = 1;
  timeinfo->tm_hour = 0;
  timeinfo->tm_min= 0;
  timeinfo->tm_sec= 0;
}

正如Shafik已经写过的,你的问题是许多*time()方法使用的内部静态std::tm。因此,只需创建自己的std::tm,或者更简单,将其用作成员而不是指针:

class timeclass {
  private:
  std::tm timeinfo;
  /* rest stays the same */
};
void timeclass::tm_init(int y) {
  timeinfo = *std::gmtime(&rawtime); // if you need gmtime
  timeinfo.tm_year = y - 1900;
  timeinfo.tm_mon = 0;
  timeinfo.tm_mday = 1;
  timeinfo.tm_hour = 0;
  timeinfo.tm_min= 0;
  timeinfo.tm_sec= 0;
}

正如其他人指出的那样,问题在于您正在使用的函数返回全局数据。所以你的问题被回避了。

然而,正如你所指出的,c++是在类级别而不是对象级别封装的,因此任何对象都可以修改同一类的任何其他对象的私有数据。

可以通过只使用抽象类作为参数和类成员来解决这个问题:

class Time {
public:
    virtual void setYear(int year) = 0;
    virtual void printDate() = 0;
    virtual void subtract(Time& otherTime) = 0;   
};