这确实是一个良好形式/最佳实践的问题。我在C ++中使用结构来形成基本上保存数据的对象,而不是创建一个具有大量访问器方法的类,这些方法除了获取/设置值之外什么都不做。例如:
struct Person {
std::string name;
DateObject dob;
(...)
};
如果你想象那里有20个变量,把它写成一个有私人成员和40多个访问者的类是很难管理的,对我来说似乎很浪费。
有时候,我可能还需要为数据添加某种最小功能。在示例中,假设我有时也需要年龄,基于dob:
struct Person {
std::string name;
DateObject dob;
(...)
int age() {return calculated age from dob;}
}
当然,对于任何复杂的功能,我都会创建一个类,但对于这样一个简单的功能,这是“糟糕的设计”吗?如果我确实使用了一个类,那么将数据变量保存为公共类成员是不好的形式,还是只需要接受它并使用一堆访问器方法创建类?我理解类和结构之间的差异,我只是询问最佳实践。
答案 0 :(得分:22)
我认为这里有两个重要的设计原则:
如果该类中存在某些不变量,则通过界面隐藏类的表示。
当存在该类的无效状态时,类具有不变量。班级应该始终保持不变。
考虑表示2D几何点的Point
类型。这应该是struct
个公共x
和y
数据成员。没有无效点这样的东西。 x
和y
值的每个组合都非常好。
在Person
的情况下,它是否具有不变量完全取决于手头的问题。您是否将空名称视为有效名称? Person
可以有任何出生日期吗?对于你的情况,我认为答案是肯定的,你的班级应该让成员公开。
非朋友非会员功能改善了封装。
没有理由将age
函数实现为成员函数。 age
的结果可以使用Person
的公共接口计算,因此没有理由成为成员函数。将它放在与Person
相同的名称空间中,以便通过参数依赖查找找到它。 ADL找到的函数是该类接口的一部分;他们只是无法访问私人数据。
如果您确实将其设为成员函数,并且有一天将某个私有状态引入Person
,那么您将具有不必要的依赖性。突然age
可以访问超出需要的数据。
所以我将如何实现它:
struct Person {
std::string name;
DateObject dob;
};
int age(const Person& person) {
return calculated age from person.dob;
}
答案 1 :(得分:6)
在C ++中,Structs是类,只有 的区别(至少我可以想到)是Structs中的成员默认是公共的,但在类中它们是私有的。这意味着使用Structs是完全可以接受的 - this article很好地解释了它。
答案 2 :(得分:1)
在C ++中,结构和类之间的唯一区别是默认情况下结构是公开可见的。一个好的指导方针是使用结构作为普通旧数据(POD),它只保存数据并在需要更多功能(成员函数)时使用类。
您可能仍然想知道是否只在类中使用公共变量或使用成员函数;请考虑以下情况。
假设您有一个类A
,其函数GetSomeVariable
仅仅是私有变量的getter:
class A
{
double _someVariable;
public:
double GetSomeVariable() { return _someVariable; }
};
如果在20年后,该变量的含义发生变化,你必须将它乘以0.5,怎么办呢?使用吸气剂时,很简单;只返回变量乘以0.5:
double GetSomeVariable() { return 0.5*_someVariable; }
通过这样做,您可以轻松维护,并且可以轻松修改。
答案 3 :(得分:1)
如果你想要一些数据持有者,那么更喜欢没有任何get / set方法的struct。
如果还有更多内容,就像本案例“人”一样。
那么它是一个完美的候选人。
答案 4 :(得分:0)
"仅将结构用于携带数据的被动对象;其他一切都是一个班级。"
说google guidlines,我这样做,并认为这是一个很好的规则。除此之外,我认为您可以定义自己的语用学,或者如果它真的有意义,则偏离此规则。
答案 5 :(得分:0)
我不想在这里发动圣战;我通常以这种方式区分它:
struct
关键字很方便,也可以作为对象使用的提示。class
关键字的使用更为自然。答案 6 :(得分:0)
为了消除一些人的困惑!而且采摘方便!这里有几点!
在结构中!您可以拥有封装和可见性运算符(使私有或公开)!就像上课一样!
所以有人说或者你可能在网上找到的说法是:区别之一是结构没有可见性运算符和隐藏数据的能力,是错误的!
你可以像在类中一样拥有方法!
运行下面的代码!你可以检查它编译得很好!并且一切顺利!整个struct就像class一样工作!
主要区别在于可见性模式的默认设置!
结构公开了!默认为私有类!
#include<iostream>
#include<string>
using namespace std;
int main(int argv, char * argc[]) {
struct {
private:
bool _iamSuperPrivate = true;
void _sayHallo() {
cout << "Hallo mein Bruder!" << endl;
}
public:
string helloAddress = "";
void sayHellow() {
cout << "Hellow!" << endl;
if (this->helloAddress != "") {
cout << this->helloAddress << endl;
}
this->_sayHallo();
}
bool isSuperPrivateWorking() {
return this->_iamSuperPrivate;
}
} testStruct;
testStruct.helloAddress = "my Friend!";
testStruct.sayHellow();
if (testStruct.isSuperPrivateWorking()) {
cout << "Super private is working all well!" << endl;
} else {
cout << "Super private not working LOL !!!" << endl;
}
return 0;
}
在内存中它们是相同的!
我没有检查自己!但有人说,如果你做同样的事情! 结构和类之间编译后的汇编代码是一样的! (待查!)
选择任何类并将名称更改为 typedef struct !您会看到代码仍然可以正常工作!
class Client {
}
Client client(...);
=>
typedef struct Client {
....
} Client;
Client client(...);
如果你这样做,一切都会一样!至少我知道在 gcc 中是这样的!
你可以测试!在您的平台上!