方法声明后的const修饰符意味着什么? - 页 6

 
恒定方法
常量方法的区别在于它们不改变其类字段的值。我们来看看一个叫CONSTFU的例子。
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

一个普通的nonFunc()方法可以改变alpha字段的值,但一个常量方法conFunc()不能。如果试图改变α字段,编译器将报告一个错误
要使一个函数成为常量,必须在函数原型之后,但在函数体开始之前指定const关键字。如果函数声明和定义是分开的,const修饰符必须被指定两次--在函数声明和定义中。让这些只从类字段读取数据的方法成为常量是有意义的,因为它们不需要改变类对象字段的值。

使用常量函数有助于编译器检测错误,同时也告诉列表的读者,该函数不会改变对象字段的值。常量函数可以用来创建和使用常量对象,我们以后会看到。

距离类的一个例子

为了不在一个程序中包含大量的创新,到目前为止,我们在例子中没有使用常数方法。 然而,有相当多的情况下,使用常数方法会很有用。例如,在我们的例子中反复出现的Distance类的showdist()方法应该被做成常量,因为它不会(也不应该!)改变它所调用的对象的字段。它的目的只是为了在屏幕上显示字段的当前值

...

摘自第250页,Lafauré R. - Object-Oriented Programming in C++ (4th ed.) 2004

 
Dmitry Fedoseev:

这就是意思,因为在这种情况下,类型不是被谈论的。"自己的类 "显然是它自己的实例(即对象)。

_x 成员与bar方法属于同一类别。

C obj._x - 这里的_x成员是在一个外国类obj中。

对我来说,谈论一个类而不是一个实例似乎是可以接受的,因为很明显,_x属于我们的类,我们写的,而obj.x属于外国的类,我们处理的。

说到OOP的术语,这里的整个术语都有点这个意思(甚至是很多)。

Dmitry,你是否明白,如果你这样说,那些第一次用这样的术语开始熟悉OOP的人就会疯掉!你知道吗?

这就是你的意思,因为我们在这里谈论的不是一个类型。"其类 "显然是它自己的实例(即对象)。

这对你来说可能很明显。我在阅读时想,如果类是一个指令,是一个抽象,那么成员_x怎么能属于一个类,正如你自己所说。

关于交易、自动交易系统和策略测试的论坛

方法声明后的const修饰语是什么意思?

Dmitry Fedoseev, 2016.02.01 19:06

一个对象如何调用一个方法?一个方法可以从一个函数或另一个方法中调用。

它不仅仅是一个被调用的类方法,而是一个特定对象的方法。该类本身就是一个抽象概念。

C obj._x - 这里的成员_x在一个不相干的类中obj。

你真的不明白类和类的实例之间的区别吗!?你绝对不能这么说,因为这将导致读者的大脑爆炸,他会认为调用方法的对象和obj对象是不同类的实例,尽管它们是一个类的实例(在你举的例子中)。

说到OOP术语,这里的所有术语都有点这个意思(甚至是很多)。

当你不了解你正在处理的问题时,术语是 "有点事"。你只需要清楚地了解什么是类(指令),什么是类的对象(实例)。然后很多问题就会自己消失。显然,我将无法改变你的想法,所以我认为继续讨论这个问题没有意义。这是个遗憾。
 
unreal:
恒定方法
常量方法的区别在于它们不改变其类字段的值。我们来看看一个叫CONSTFU的例子。
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

一个普通的nonFunc()方法可以改变alpha字段的值,但一个常量方法conFunc()不能。如果试图改变α字段,编译器将报告一个错误
要使一个函数成为常量,必须在函数原型之后,但在函数体开始之前指定const关键字。如果函数声明和定义是分开的,const修饰符必须被指定两次--在函数声明和定义中。让这些只从类字段读取数据的方法成为常量是有意义的,因为它们不需要改变类对象字段的值。

使用常量函数有助于编译器检测错误,同时也告诉列表的读者,该函数不会改变对象字段的值。常量函数可以用来创建和使用常量对象,我们以后会看到。

距离类的一个例子

为了不在一个程序中包括许多创新,到目前为止,我们没有在我们的例子中使用常数方法。 然而,有相当多的情况下,使用常数方法会很有用。例如,在我们的例子中反复出现的Distance类的showdist()方法应该被做成常量,因为它不会(也不应该!)改变它所调用的对象的字段。它的目的只是为了在屏幕上显示字段的当前值

...

摘自第250页,Lafauré R. - Object-Oriented Programming in C++ (4th ed.) 2004

但是,如果在一本关于OOP的书中,他们写的要么是正确的,要么是错误的,那么你的头脑中会有什么秩序呢?虽然,也许,是翻译的问题。
 
Alexey Kozitsyn:

Dmitry,你是否明白,如果你这样说话,那些第一次用这种术语开始熟悉OOP的人就会发疯?

这对你来说可能很明显。我在阅读和思考,如果一个类是一个指令,一个抽象,就像你自己说的那样,一个成员_x怎么能属于一个类。

你真的不明白类和类的实例之间的区别!?你绝对不能这么说,因为这会引起读者的大脑爆炸,他会认为调用方法的对象和obj对象是不同类的实例,尽管它们是同一个类的实例(在你举的例子中)。

当你不了解你正在处理的问题时,术语就会 "有点那个"。你只需要清楚地了解什么是类(指令),什么是类的对象(实例)。然后很多问题就会自己消失。显然,我将无法改变你的想法,所以我认为继续讨论这个问题没有意义。这是个遗憾。

你为什么要改变我的想法?改变你对什么的看法?对我来说,一切都很好。这个主题的第一篇帖子足以让我有一个完全没有冲突的理解。

还要注意的是,是你写的,参考资料就可以理解了。所以根本就不清楚你在争论什么?

ps.不要把你自己的一堆妄想归于我。

 
George Merts:

就我个人而言,我一直把const-methods理解为不能改变类变量的方法。

我很少使用它们,因为我经常遇到这样的情况:方法的重新定义需要改变一些东西,而基础方法是不变的(这里已经提到过)。

静态方法得到了广泛的使用。在几乎任何复杂的类中。通常,这些都是 "服务性 "的附加方法,不需要访问类的变量。

此外,对于像 "一天中的秒数 "这样的常量,我尝试使用静态常量结构而不是#define。在这种情况下,这种常量的声明和初始化是在不同的地方,但类型控制出现了,而且它不止一次地帮助我。

同样的东西,我很少使用。事实上,我发起这个话题是因为这个论坛的一个参与者在私人信息中问我为什么需要它们。
 
George Merts:

就我个人而言,我一直把const-methods理解为不能改变类变量的方法。

我很少使用它们,因为我不止一次遇到过这样的情况:方法覆盖需要改变一些东西,而基础方法是不变的(这里已经提到过)

你不是因为这个原因而使用它们,而我确实是因为这个原因而使用它们。

zaskok3:

对我来说,使用常量和静态大大增加了我自己代码的可读性/理解性。并允许你经常在自己的架构实施的早期就能发现其中的错误或 缺陷。


我写的一切只为自己。而且似乎我不会改变一些反正不应该改变的数据。但是,保护自己不受自己的愚蠢行为影响的愿望使我把OOP架构铆在一起,只有那些必须可以访问的东西才可以改变。其余的则没有。而在这里,const + 继承类型有很大的帮助。我推荐它。
 

请好心人帮助编译EA,我不擅长编程。

这是我在编译'delete'时得到的错误--预期的名称

代码中的错误以红色显示

空白删除(int type){

如果(OrdersTotal()>0){

for(i=OrdersTotal()-1;i>=0;i--){

OrderSelect(i,SELECT_BY_POS,MODE_TRADES)。

if(type!=6 && type!=7 && type!=8)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType() ==type)OrderDelete(OrderTicket();

如果(type==6)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic &&)OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP || OrderType()==OP_BUYLIMIT || OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket())。

if(type==7)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType()==OP_BUYSTOP || OrderType()==OP_BUYLIMIT)OrderDelete(OrderTicket() )。

如果(type==8)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType()==OP_SELLSTOP || OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket())。

}

}

}


这里有另一个错误'(' - 预期的对象指针

如果(反对删除){删除(OP_SELLSTOP);删除(OP_SELLLIMIT);}。

而这里的'}'- 不是所有的控制路径都会返回一个值

int countglobal(){

int cnt=0。

如果(OrdersTotal()>0){

for(i=OrdersTotal()-1;i>=0;i--){

OrderSelect(i,SELECT_BY_POS,MODE_TRADES)。

cnt++。

}

return(cnt)。

}

}

 
zaskok3:

你不是因为这个原因而使用它们,而我确实是因为这个原因而使用它们。

我同意,在阅读和理解长篇大论的函数时,const指定符很有用。但在我看来,通过在不同的私有-保护-公共部分声明变量,限制 对变量的访问 似乎更有意义(我个人从不把变量声明为公共的,只声明方法)。

我很难想象在什么情况下内部的类变量不应该在后代中被修改。

 
Anton Razmyslov:

请好心人帮助编纂EA,我不擅长编程。

在逻辑上呢?为什么要用这样的问题来扰乱一个无关紧要的话题?
 

顺便说一下,没有人写过Const修改器不仅不允许改变自己类中的数据,甚至不允许处理非常量方法。一个简单的例子:有一个头寸类,我们需要按利润对头寸列表进行排序。利润是按要求计算的。

class CPosition : public CObject
{
private:
   double m_profit;
   void CalculateProfit()
   {
      m_profit = 31337;
   }
public:
   CPosition(void) : m_profit(0.0)
   {
   }
   double Profit(void)const
   {
      if(m_profit == 0.0)
         CalculateProfit(); // <- Константный метод вызывает блок рассчета и вызывает ошибку
      return m_profit;
   }
   virtual int Compare(const CObject *node,const int mode=0) const
   {
      const CPosition* pos = node;
      if(pos.Profit() > Profit())
         return 1;
      else if(pos.Profit() < Profit())
         return -1;
      return 0;
   }
};

这段代码将导致一个错误,因为尽管 "利润 "方法是常数,但如果利润还没有被计算出来,它将引用非常数方法CalcultaeProfit。

请注意,Profit方法本身是绝对安全的:它保证其返回的值不是空的。然而,恒定的方法 要求放弃幕后计算和高代码安全性,而采用一些开箱即用的结构,这些结构不知道它们限制什么和为什么。