c++实现文件中的getter语言 - setter

C++ Getters-Setters in Implementation File

本文关键字:语言 setter getter 实现 文件 c++      更新时间:2023-10-16

我对c++比较陌生,我认为我的问题可以通过例子来理解。在头文件中,假设我有

class myClass{
    public:
        double getVar1();
        void setVar1(double newVar1);
        void copyVar1(myClass* dat);
    private:
        double var1;
};

在我的实现。cc文件中,当实现copyVar1方法时,我是否应该执行

void myClass::copyVar1(myClass* dat){
   var1 = dat->var1;
}

void myClass::copyVar1(myClass* dat){
   var1 = dat->getVar1();
}

,在第二种情况下,我使用getter方法代替。两者都在Visual c++中正常工作,但我想知道在实践中使用哪个更好。

谢谢你的评论!

最佳实践?重载赋值操作符,而不是编写方法。

myClass & myClass::operator=(const myClass & dat)
{
   var1 = dat.var1; // or dat.getVar1()
   return *this;
}

至于使用字段或调用setter…这完全是个人品味的问题。如果你的getter有一些副作用,那么你可能应该调用它,否则,使用该字段。

所以,一个很大的"看情况"。

当您在类之外访问变量时,您应该几乎总是使用getter/setter方法,而且通常您必须这样做,因为这是唯一的方法。但是,当您在类内部时,您可以使用任何一种方法,并且如果getter方法除了返回变量之外什么也不做,则不会有什么区别。

你的决定将基于你是否在getter方法中有代码做一些不仅仅是返回变量的事情,以及如果你想在copyVar1被调用时运行该代码。如果您不知道,我的建议是,如果您将来决定更改中的代码,仍然使用getter方法。虽然它现在可以很好地直接访问它,而且你可能会有微观上更好的性能,但当你不应该调用getter时发现错误要比在你应该调用它时没有调用它容易得多。编译器最终可能会优化到您甚至感觉不到差异的程度。:D

我更喜欢这样使用setter和getter,如果你改变一些实现细节(例如引入值赋值的验证),你可能不得不在setter的一个地方改变…

看情况。许多人会告诉您,使用getter/setter而不是变量更容易避免编程错误和更改,并减少代码重复。但只要这些getter/setter不是内联函数,你可能会得到一个小的性能打击,因为实现必须知道类的内部,为什么不直接使用变量。

您正在尝试编写复制构造函数吗?当有setVar1时,为什么还需要copyVar1 ?如果您试图编写复制构造函数,最好不要使用getter。

myclass(const myclass& other)
{
var1 = other.var1;
}

当你同时拥有getter和setter时,为什么不将var1设为public呢?

在这里没有正确或错误的方法。

但是,假设getVar1()返回值或var1。如果您决定更改var1值的存储方式,那么您需要遍历所有代码并更新它。使用setter/getter将其减少为几个方法。在这种情况下,您应该使用第三个选项:

void myClass::copyVar1(myClass* dat){
   setVar1 (dat->getVar1());
}

,然后完全删除对var1的依赖,您可以将var1更改为其他内容,copyVar1仍然可以工作。

正如你所说,两者都可以正常工作并且完全合法。

在某种意义上,直接访问成员变量和使用访问器的区别在于你在类中定义了一个更强的"层";与其他层一样,这一层可以帮助您减少依赖关系。

换句话说,getter方法基本上满足了不向外界披露实现细节的要求;比如说,你可能有一天决定不把var1存储为双精度体,而是计算它。因此,访问器为您提供了这种自由:在某种程度上,您可以在不影响其他类(即减少依赖)的情况下更改实现。

在类本身中使用getter方法也是如此,也就是说,您正在删除类范围内的依赖项,并且您的设计更能适应更改。

对setter和getter进行抽象的意义在于,检索的方法可能会发生变化。当您直接访问成员变量时,如果有任何变化,您必须在所有地方更新您的用法。但是如果您使用函数,那么更改变量检索方式只需要在函数中更改即可。

现在,因为这是同一个类,所以它比将变量设为公共时要少得多,因为您只需要更新这一个实现文件(而不是更新类的每个用户,如果您有一个库类,这可能是不可能的)。

要了解这一点,看一下突然需要使线程安全的类。现在,你的复印机看起来像

void myClass::copyVar1(myClass * dat)
{
    scoped_lock lock(mutex);
    var1 = dat->getVar1();
}

,如果总是按函数调用,则不必修复其他任何地方。如果您直接访问该变量,那么它将看起来像

void myClass::copyVar1(myClass * dat)
{
    scoped_lock lock(mutex);
    scoped_lock lock2(dat->mutex)
    var1 = dat->var1;
}

将"data"的互斥锁在data之外,通常不被认为是一个很好的设计(如果你让工程师必须记住锁定其他人的对象,那么你就有可能让他们忘记并不这样做)。

类似地,如果变量开始存储在数据库中,您也必须处理它。或者,如果变量现在存储在两个不同的变量中,并在检索它时构造,那么您可以看到复杂性将如何增加。

但是请记住,使用访问器和mutator的设计理念是通过封装来降低潜在的复杂性。有时候,当你在做小项目(尤其是个人项目)时,你根本不想改变课程。直接访问它们可能不那么复杂。不要害怕这样做,只要知道你为什么要做这个决定。