未完全封装的私有类成员
Private class members not fully encapsulated?
这是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;
};
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 当从成员类调用封装的std::begin时,程序崩溃
- 从私有成员类中断封装派生的模板类
- 是否有更好的方法来封装成员对象可以访问的共享存储池?
- 如何访问封装向量中的元素的公共成员
- std::memcpy结构,具有TriviallyCopyable类型T的紧密封装成员到T的数组,反之亦然
- C++封装成员的完美转发/代理
- 通过向成员返回非常量引用来破坏封装
- 静态成员和c++中的封装
- 传递 lambda 在使用私有成员变量时是否违反封装
- 我应该通过引用、值或ptr来存储一个完全封装的成员吗
- 命名空间或类,这更适合只封装函数成员
- 从外部调用封装类成员函数时不加载SFML纹理
- 如何将数组作为私有类成员并确保适当的封装?
- 在ARM上的c++结构成员对齐和封装要求
- 未完全封装的私有类成员