C++ 将某些特定于类的功能作为单独的函数而不是成员函数的原因是什么?
在查看比较旧的代码时,我发现了一些奇怪的设计决策:C++ 将某些特定于类的功能作为单独的函数而不是成员函数的原因是什么?,c++,oop,C++,Oop,在查看比较旧的代码时,我发现了一些奇怪的设计决策: // irrelevant stuff removed class Class { public: int GetStage() const { return stage; } void SetStage( int value ) { stage = value; } private: int stage; }; void ProgressStage( Class* object ) { int stage = ob
// irrelevant stuff removed
class Class {
public:
int GetStage() const { return stage; }
void SetStage( int value ) { stage = value; }
private:
int stage;
};
void ProgressStage( Class* object )
{
int stage = object->GetStage();
assert( stage < MaxStage );
stage++;
object->SetStage( stage );
}
选择前者而不是后者的原因是什么?没有很好的理由选择该功能。 C++不是纯面向对象的,因为它允许你写函数而不是方法。p> 另外,您使用阶段临时变量的原因是什么?这是为了维护安全吗?我想把它改成:
assert(stage+1 <= MaxStage);
++stage;
没有充分的理由选择该功能。 C++不是纯面向对象的,因为它允许你写函数而不是方法。p> 另外,您使用阶段临时变量的原因是什么?这是为了维护安全吗?我想把它改成:
assert(stage+1 <= MaxStage);
++stage;
在我看来,这个类似乎是一个数据对象DAO,因为不包括任何业务逻辑。可能他们想将业务逻辑与实体层分离。但是我不知道为什么他们没有将业务逻辑放入manager类或类似的类中。在我看来,这个类似乎是一个数据对象DAO,因为没有包含业务逻辑。可能他们想将业务逻辑与实体层分离。但我不知道为什么他们没有把业务逻辑放到管理器类中或者类似的东西。在C++中,自由函数是做事情的首选方式。类应该提供一个最小的接口来完成它的工作。语言功能(如参数相关查找)用于将自由函数与操作数类相关联。这些函数为接口添加了糖 以下是标准委员会杰出成员Herb Sutter的一篇论文: 编辑:现在我真的停下来读了你的代码,这看起来太过分了。类似乎要做的唯一工作是确保stage
假设阶段不能被跳过或反转,也许SetStage应该被删除,AdvanceStage应该在类中移动。无论如何,StEffice应该包含断言,而不是自由函数。C++中的< P>,自由函数是首选的做事方式。类应该提供一个最小的接口来完成它的工作。语言功能(如参数相关查找)用于将自由函数与操作数类相关联。这些函数为接口添加了糖 以下是标准委员会杰出成员Herb Sutter的一篇论文: 编辑:现在我真的停下来读了你的代码,这看起来太过分了。类似乎要做的唯一工作是确保stage
假设阶段不能被跳过或反转,也许SetStage应该被删除,AdvanceStage应该在类中移动。在任何情况下,SetStage似乎应该包含该断言,而不是自由函数。虽然我同意你的观点,但有些人认为任何可以使用类的公共接口的现有功能实现的函数都应该成为非成员。我想这是一种最小但完全的心态 就我个人而言,我同意你的看法,作为一名会员,这种感觉更加自然和一致
如果类是一个结构,我会说它可能会被导出到一个C-可调用接口中,但对于一个类来说,这是不可能的,除非你使用一个空指针。虽然我同意你的观点,有些人认为,任何可以使用类的公共接口的现有功能实现的函数都应该成为非成员。我想这是一种最小但完全的心态 就我个人而言,我同意你的看法,作为一名会员,这种感觉更加自然和一致
如果类是一个结构,我会说它可能会被导出到一个C-可调用接口中,但对于类来说,这是不可能的,除非您使用void指针。非成员函数用作回调时更容易键入较少的内容。非成员函数用作回调时更容易键入较少的内容。我只想使用:
class Class {
public:
bounded<unsigned, 0, MaxStage> stage;
};
使用我发布的绑定模板。这确实假设/要求MaxStage是一个常数。如果不是,您可以使用相同思想的变体,将边界传递给ctor,这对有界浮点类型也很有用。我只使用:
class Class {
public:
bounded<unsigned, 0, MaxStage> stage;
};
使用我发布的绑定模板。这确实假设/要求MaxStage是一个常数。如果不是,您可以使用相同思想的变体,将边界传递给ctor,这对于有界浮点类型也很有用。原因很简单,这是一个更好的解决方案 为什么您希望函数成为成员方法?这样它就可以访问它不需要的所有私有成员 问问你自己,如果你不喜欢使用getter和setter,为什么这个类有getter和setter?你的建议是基本的 凯莉毫无理由地绕过他们 通过最小化可以访问类内部的代码量,使其成为一个自由函数可以更好地保留封装
这是C++中的惯用解决方案,如描述的或./P> 基本的经验法则应该始终是:在非成员函数中放置尽可能多的类功能。能够看到类内部的代码越少,当您更改该类的实现时,代码被破坏的风险就越小
这个模型没有什么特别面向对象的。操作人员因此,使用它并不一定会使代码更加面向对象或更好。原因很简单,它是一个更好的解决方案 为什么您希望函数成为成员方法?这样它就可以访问它不需要的所有私有成员 问问你自己,如果你不喜欢使用getter和setter,为什么这个类有getter和setter?你的建议基本上是毫无理由地绕过它们 通过最小化可以访问类内部的代码量,使其成为一个自由函数可以更好地保留封装
这是C++中的惯用解决方案,如描述的或./P> 基本的经验法则应该始终是:在非成员函数中放置尽可能多的类功能。能够看到类内部的代码越少,当您更改该类的实现时,代码被破坏的风险就越小
这个模型没有什么特别面向对象的。操作人员使用它并不一定会让你的代码更加面向对象或更好。这可能是一个愚蠢的问题,但是:为什么不把舞台公诸于众,然后做:c类;c、 舞台++?好吧,除非ProgressStage做了其他你没有提到的事情。相关问题:@ereOn:第一个原因是断言可以防止误用。实际上,这个问题的假设是错误的:拥有一个只有getter和setter的类是愚蠢的。这不是OO,这是伪OO。它是一个包含所有公共数据的美化结构,从某种意义上说,单例是一个美化的全局变量——只不过更糟。这也许是一个愚蠢的问题,但是:为什么不把舞台公之于众,去做:c级;c、 舞台++?好吧,除非ProgressStage做了其他你没有提到的事情。相关问题:@ereOn:第一个原因是断言可以防止误用。实际上,这个问题的假设是错误的:拥有一个只有getter和setter的类是愚蠢的。这不是OO,这是伪OO。它是一个包含所有公共数据的美化结构,从某种意义上说,单例是一个美化的全局变量——只不过更糟。你知道,大多数面向对象的定义实际上并不包括所有函数,它们必须是一个类的成员。这正是Java提出的。而且有几个很好的理由支持免费功能。@jalf我不同意。面向对象是一种古老的方法,不是java和C++工程师发明的。封装呢?如果你写C++代码而不是C,也许你对使用OO范式感兴趣,而自由函数就像任何静态方法一样打破它们。你知道,大多数面向对象的定义实际上并不包括所有函数都必须是一个类的成员。这正是Java提出的。而且有几个很好的理由支持免费功能。@jalf我不同意。面向对象是一种古老的方法,不是java和C++工程师发明的。封装呢?如果你正在编写C++代码而不是C,也许你对使用OO范式感兴趣,而自由函数就像任何静态方法一样打破它们。同意,这就是Scott Meyer在其有效的C++第三版中解释的,项目23:更喜欢非成员非朋友函数到成员函数。这样做可以提高封装性、封装灵活性和功能扩展性。对此我完全不同意。如果开发人员可以访问类的源代码,并且可以在不破坏其他类客户端的情况下对其进行修改,那么就没有真正的理由使用单独的函数来增加类本身的内部变量。考虑一下类开发人员是否想改变他类的其他版本中PrimeStError方法的实现。同意,这是Scott Meyer在其有效的C++第三版中解释的,项目23:更喜欢非成员非朋友函数到成员函数。这样做可以提高封装性、封装灵活性和功能扩展性。对此我完全不同意。如果开发人员可以访问类的源代码,并且可以在不破坏其他类客户端的情况下对其进行修改,那么就没有真正的理由使用单独的函数来增加类本身的内部变量。考虑类开发人员是否希望更改程序的实现
在他的类的其他版本中使用ssStage方法。这可能是正确的答案。ProcessStage是一个简单的函数,因此可以在需要函数指针的地方进行传递,而不会出现任何问题。这可能是正确的答案。ProcessStage是一个简单的函数,因此可以在需要函数指针的地方进行传递,而不会出现任何问题。