1

这是Instance-level encapsulation with 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++ 仅支持类级封装,并且想知道我的问题是否是因为同一类的成员可以访问彼此的私有成员。有没有办法解决这个问题,所以我可以实现我想做的事情?谢谢你,泰勒

4

3 回答 3

5

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

其他答案为此限制提供了可能的解决方法。

于 2013-03-08T21:16:16.293 回答
2

您实际上并不想要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 已经写的那样,您的问题是您指向std::tm的许多方法使用的内部静态。*time()因此,只需创建自己的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;
}
于 2013-03-08T21:19:24.670 回答
0

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

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

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

class Time {
public:
    virtual void setYear(int year) = 0;
    virtual void printDate() = 0;
    virtual void subtract(Time& otherTime) = 0;   
};
于 2013-03-08T21:35:19.997 回答