或者是吗?
如果有一个同样有用的构造可以正确隐藏数据成员,那么面向对象的设计是否应该使用默认情况下公开成员数据的语言结构?
编辑:其中一位回应者提到,如果没有不变量,可以使用结构。这是一个有趣的观察结果:结构是一种数据结构,即它包含相关数据。如果结构中的数据成员是相关的,那么总是存在不变量吗?答案 0 :(得分:18)
在C ++中, struct 和 class es除了其成员的默认公共/私有性外是相同的。 (此默认设置很容易,通常会被覆盖。)
但是,大多数程序员将结构视为“数据对象”,将类视为“交互式对象”。那不是坏事;事实上应该利用。如果某些东西只是一个无生命的数据块(即使可能有一些检查器方法),请使用它的结构;当程序员试图查看它的用途时,它会节省一些精力。
答案 1 :(得分:13)
不要成为隐藏的狂热者。如果你的get / set方法什么都不做,只是简单地将值逐字复制到隐藏的私有字段上,你就没有获得公共成员的任何东西,只会不必要地使你的类复杂化(并且,根据编译器的智能,慢它的用法有点)。
有一种情况是,当你的setter方法做一些验证时不允许直接访问,在其他地方复制数据,在存储它之前稍微处理它,等等。在实际计算的getter的情况下他们从多个内部来源返回的价值,并隐藏其衍生方式(我相信Bertrand Meyer在他的书中谈到这一点)
或者,如果允许您的类的用户直接更改此类值,则会产生意外的副作用,或者会打破您的某些成员类关于值的假设。在这些情况下,无论如何都要隐藏你的价值观。
例如,对于一个简单的“Point”类,它只包含几个坐标和颜色,以及在屏幕上“绘制”它并“隐藏”它的方法,我认为不允许用户直接使用设置其字段的值。
答案 2 :(得分:4)
例如,在C#中,我将结构用于一些简单的更好左值数据类型:
public struct Point
{
int X;
int Y;
}
对于任何P / Invoke到参数是结构的库,你必须肯定使用它们。
它们属于应用程序的一般设计吗?当然他们这样做,在有意义的时候使用结构。就像你在有意义的情况下使用带有位标志的枚举一样,而不是通过一些复杂的字符串解析来存储组合值。
答案 3 :(得分:4)
在C ++中,结构和类之间的区别是其内容的默认可见性(即对于结构是公共的,对于类是私有的)。我想这种差异是为了保持C兼容性。
但从语义上讲,我想这可以解释。
在结构中,一切都是公共的(默认情况下),这意味着用户可以根据需要修改每个数据值,并且结构仍然是有效对象。结构示例:
struct CPoint
{
int x ;
int y ;
CPoint() : x(0), y(0) {}
int getDistanceFromOrigin() const
{
return std::sqrt(x * x + y * y) ;
}
} ;
inline CPoint operator + (const CPoint & lhs, const CPoint & rhs)
{
CPoint r(lhs) ;
r.x += rhs.x ;
r.y += rhs.y ;
return r ;
}
您可以更改CPoint的x值,它仍然是有效的CPoint。
请注意,与某些人不同,C ++结构可以(并且应该)具有附加到其接口的构造函数,方法和非成员函数,如上所示。
在类中,一切都是私有的(默认情况下),这意味着用户只能通过定义良好的接口修改数据,因为类必须保持其内部有效。上课的例子:
class CString
{
public :
CString(const char * p) { /* etc. */ } ;
CString(const CString & p) { /* etc. */ } ;
const char * getString() const { return this->m_pString ; }
size_t getSize() const { return this->m_iSize ; }
void copy { /* code for string copy */ }
void concat { /* code for string concatenation */ }
private :
size_t m_iSize ;
char * m_pString ;
} ;
inline CString operator + (const CString & lhs, const CString & rhs)
{
CString r(lhs) ;
r.concat(rhs) ;
return r ;
}
您会看到,当您调用concat时,指针都需要重新分配(以增加其大小),并且必须自动更新字符串的大小。您不能让用户手动修改字符串,忘记更新大小。
因此,该类必须保护其内部,并确保在需要时所有内容都会正确更新。
对我来说,结构和类之间的区别在于聚合数据之间的依赖关系。
如果每个数据都独立于所有其他数据,那么您可能应该考虑一个结构(即具有公共数据成员的类)。
如果没有,或者有疑问,请使用课程。
现在,当然,在C#中,struct和class是两种不同类型的对象(即结构的值类型和类的引用类型)。但是我想这是出于这个话题。
答案 4 :(得分:2)
事情很简单。如果class
确实有不变量来保证,那么你永远不应该让成员限制不变的公共。
如果您的struct
仅仅是不同对象的汇总,并且没有固定不变量,那么您确实是自由的,并鼓励其成员public
。这就是C ++中std::pair<T, U>
的方式。
简单示例:假设您有一个Point
类,其x and y
成员必须始终为>= 0
。你可以做一个不变的陈述
/* x >= 0 && y >= 0 for this classes' objects. */
如果您现在将这些成员公开,客户可以简单地更改x和y,并且您的不变量可能会轻易破坏。但是,如果允许成员分别包含适合他们自己的不变量的所有可能的值,那么当然可以公开这些成员:无论如何你都不会给他们添加任何保护。
答案 5 :(得分:2)
从技术上讲,struct是一个默认可见public的类(真正的类具有private的默认可见性)。
在共同使用方面有更多区别。
结构通常只是一组数据,需要由其他代码检查和处理。
一个类通常更重要,它保持对其数据的某种控制,以及相关函数指定的行为。
通常情况下,类更有用,但是每隔一段时间就会出现类似C结构的用法,并且有一个符号差异来显示它。
答案 6 :(得分:1)
结构本质上是一个模型类,但语法不同。
public struct Point {
int x;
int y;
}
在逻辑上与:
相同public class Point {
private int x;
private int y;
public void setX(int x) { this.x=x; }
public int getX(); { return x; }
public void setY(int y) { this.y=y; }
public int getY(); { return y; }
}
两者都是一个可变模型,它包含一对称为x和y的整数值。所以我想说它是一个有效的面向对象的构造。
答案 7 :(得分:0)
我经常使用结构 - 主要用于从网络或硬件接收的数据。它们通常包含在一个类中,供程序的更高级别部分使用。
我的经验法则是结构总是纯数据,除了构造函数。别的什么都是上课。
答案 8 :(得分:0)
使用结构本身并没有错,但如果你发现自己需要结构,你应该问你的分析有什么问题。例如,考虑上面的Point类:它在可读性方面略有改进,因为你总是可以使用
Point foo;
//...
foo.x = bar;
代替,例如,在
中有一个双元素数组#define X 0
#define Y 1
//...
foo[X] = bar;
但是课程意味着隐藏合同背后的细节。如果您的Point位于某个标准化空间中,则值的范围可以是半开区间[0.0..1.0];如果它是一个屏幕,它们可能在[0..1023]范围内。如果您使用结构代替访问者,当foo.x = 1023
应该在任何地方x
时,如何阻止某人分配< 1.0
?
C ++程序员使用针对Points的结构的唯一原因是早在20年前,当C ++是新的时候 - 内联处理不好,所以foo.setX(1023)
实际上比foo.x = 1023
采取了更多的指示。那不再是真的。
答案 9 :(得分:0)
请参阅以下类似问题:
When should you use a class vs a struct in C++?
What are the differences between struct and class in C++
加:
根据C++ Programming Language中的Stroustrup:
您使用哪种款式取决于环境和品味。我通常更喜欢将
struct
用于公开所有数据的类。我认为这类“不太合适,只是数据结构。”
答案 10 :(得分:0)
如果需要invariant,请将其设为课程。否则,struct就可以了。
答案 11 :(得分:0)
C或C ++中使用的结构体和C#(或任何.Net语言)中使用的结构体是如此不同的动物,它们可能甚至不应该具有相同的名称......几乎任何有关结构的概括在另一种语言中,用一种语言很容易就是虚假的,或者对于一种完全无关的理由是真的。
答案 12 :(得分:0)
大多数答案似乎都支持结构作为可接受和有用的东西,只要它没有行为(即方法)。这看起来很公平。
但是,您永远不能确定您的对象不会演变成可能需要行为的东西,因此可以控制其数据成员。如果您足够幸运,您可以控制结构的所有用户,则可以查看所有数据成员的所有使用情况。但是,如果您无法访问所有用户,该怎么办?
答案 13 :(得分:0)
是。它就像一个迷你级。
答案 14 :(得分:0)
是的,他们这样做。它们具有与类不同的语义。结构通常被视为值类型,而类通常被视为并被视为引用类型。差异并不是每天编程中都有的差异;然而,当涉及到编组,COM互操作和传递实例时,它是一个重要的区别。
答案 15 :(得分:0)
形式上,在C ++中,struct是一个类,默认情况下其成员的可见性设置为public。传统结构用于对同类数据的收集进行分组,这些数据没有特定原因可供特定方法访问。 其成员的公开可见性使得结构首选于类以实现策略类和元函数。
答案 16 :(得分:-1)
结构很好,只要它们保持小。您可能知道,它们是在堆栈(而不是堆)上分配的,因此您需要查看大小。对于像Point,Size等小数据结构,它们可以派上用场。但是,类通常是更好的选择,作为引用类型和所有类。