어떤 시나리오 에서 C ++에서 struct
vs 를 사용하는 것이 더 낫 class
습니까?
어떤 시나리오 에서 C ++에서 struct
vs 를 사용하는 것이 더 낫 class
습니까?
답변:
C ++에서 a class
와 a의 차이점은 struct
구조체에 기본 public
멤버와 기본이 있고 클래스에는 기본 private
멤버와 기본이 있다는 것입니다. 두 클래스와 구조체는의 혼합물을 가질 수 있습니다 public
, protected
그리고 private
회원들은 상속을 사용할 수 있으며 멤버 함수를 가질 수 있습니다.
클래스와 같은 기능이없는 평범한 데이터 구조로 구조체를 사용하고 private
데이터 및 멤버 함수가있는 집계 데이터 구조로 클래스를 사용하는 것이 좋습니다 .
다른 사람들이 지적했듯이 실제로 두 가지 실제 언어 차이가 있습니다.
struct
기본적으로 공개 액세스로, class
기본적으로 개인 액세스로 설정됩니다.struct
기본값은 public
상속이고 class
기본값은 private
상속입니다. (C ++의 많은 것들과 마찬가지로, 기본적으로 거꾸로되어 있습니다. public
상속은 훨씬 일반적인 선택이지만 사람들 struct
은 " public
"키워드 를 입력하는 것을 막기 위해 거의 선언하지 않습니다 .그러나 실제로 진짜 차이는 사이에 class
/ struct
하지 않는 생성자 / 소멸자를 선언 한. "일반 데이터"POD 유형에 대한 보증이 있으며, 클래스 구성을 인수 한 후에는 더 이상 적용되지 않습니다. 이러한 차이를 명확하게 유지하기 위해 많은 사람들이 의도적으로 struct
POD 유형 에만 s를 사용 하고, 메소드를 추가하려는 경우 class
es를 사용 합니다. 아래 두 조각의 차이점은 의미가 없습니다.
class X
{
public:
// ...
};
struct X
{
// ...
};
(우연히, 여기에 "POD 유형"이 실제로 무엇을 의미하는지에 대한 좋은 설명이있는 스레드가 있습니다 : C ++의 POD 유형은 무엇입니까? )
struct
또는 class
개체가 POD 여부에 관계가 없습니다하거나 복사 생성자 / 소멸자를 정의할지 여부를 지정합니다. 멤버 함수는 또한 POD와 관련이 없습니다. 당신이 쓴 것을 다시 읽을 때, 당신이 다른 것을 제안하지는 않지만 현재의 말은 혼란 스럽습니다.
기존 답변에는 많은 오해가 있습니다.
예. 클래스를 선언하는 데 사용한 키워드에 따라 클래스 정의 내에서 액세스 수정 키워드를 다시 정렬해야 할 수도 있습니다.
그러나 구문을 넘어서서 하나를 다른 하나보다 선택해야하는 유일한 이유는 컨벤션 / 스타일 / 환경 설정입니다.
어떤 사람들은 struct
멤버 함수가없는 클래스에 대한 키워드 를 고집하는 것을 좋아 합니다. 결과적인 정의는 C의 간단한 구조처럼 보입니다.
마찬가지로 일부 사람들 은 "클래스"라고 class
하는 멤버 함수 및 private
데이터가 포함 된 클래스에 키워드 를 사용하기를 좋아하므로 객체 지향 프로그래밍에 대한 좋아하는 책에서 예제처럼 보입니다.
현실은 이것이 당신과 당신의 팀에게 전적으로 달려 있으며, 그것은 당신의 프로그램에 문자 그대로 아무런 영향을 미치지 않을 것입니다.
다음 두 클래스는 이름을 제외한 모든면에서 완전히 동일합니다.
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
다시 선언 할 때 키워드를 전환 할 수도 있습니다.
class Foo;
struct Bar;
(이것은 부적합으로 인해 Visual Studio 빌드를 중단 하더라도이 작업을 수행 할 때 컴파일러에서 경고를 표시합니다.)
다음 표현식은 모두 true로 평가됩니다.
std::is_class<Foo>::value
std::is_class<Bar>::value
그러나 재정의 할 때 키워드를 전환 할 수는 없습니다 . 이는 (한 정의 규칙에 따라) 번역 단위에 걸쳐 클래스 정의가 중복 되어 "동일한 토큰 시퀀스로 구성 되어야 "하기 때문 입니다. 이 방법은 당신도 교환 할 수 const int member;
와 함께 int const member;
, 그리고 의미와는 아무 상관이 없습니다 class
또는 struct
.
class foo { public: ... };
을 가질 수 있고 또 다른 번역 단위 struct foo { ... };
는 "절대적으로 동등한"주장에 따라 사실을 유지해야 한다는 것을 확신하지 못한다 . 불완전한 선언 struct foo;
과 class foo;
상호 교환 가능한 이유 가 있습니다. 이것들은 클래스 본문을 지정하지 않으므로 액세스 레이아웃에 아무 것도 말하지 않습니다.
Foo
및 Bar
정지 / 동일 유형 동등하다. 나는 " 재 선언 할 때 " 라고 말하고 예를 들었다 . 내가 UB에 있는지 내가 오해의 소지가 아니에요 사람들을 위해이 질문에 대해 답이 명확 것이다 그것을 생각 해 보 니,
클래스 대신 구조체를 사용하는 유일한 경우는 함수 호출에서 펑터를 사용하기 직전에 선언하고 명확성을 위해 구문을 최소화하려는 경우입니다. 예 :
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
로부터 C ++ FAQ 라이트 :
구조체의 멤버와 기본 클래스는 기본적으로 public이고 클래스에서는 기본적으로 private입니다. 참고 : 기본 클래스에 의존하지 않고 기본 클래스를 명시 적으로 공개, 개인 또는 보호로 설정해야합니다.
구조체와 클래스는 기능적으로 동일합니다.
으스스하고 깨끗한 테크노 대화는 충분합니다. 감정적으로, 대부분의 개발자는 클래스와 구조체를 강력하게 구분합니다. 구조체는 단순히 캡슐화 또는 기능 방식이 거의없는 열린 비트 더미처럼 느껴집니다. 클래스는 지능적인 서비스, 강력한 캡슐화 장벽 및 잘 정의 된 인터페이스를 갖춘 살아 있고 책임감있는 사회 구성원입니다. 그것이 대부분의 사람들이 이미 가지고있는 의미이므로, 메소드가 거의없고 공개 데이터가있는 클래스가있는 경우 struct 키워드를 사용해야합니다 (이러한 것들은 잘 설계된 시스템에 존재합니다!) 예어.
구조체가 나에게 도움이 된 곳은 다른 시스템에서 고정 형식 메시지 (예 : 직렬 포트)를받는 시스템이있을 때입니다. 바이트 스트림을 필드를 정의하는 구조체로 캐스트 한 다음 필드에 쉽게 액세스 할 수 있습니다.
typedef struct
{
int messageId;
int messageCounter;
int messageData;
} tMessageType;
void processMessage(unsigned char *rawMessage)
{
tMessageType *messageFields = (tMessageType *)rawMessage;
printf("MessageId is %d\n", messageFields->messageId);
}
분명히 이것은 C에서와 같은 일이지만 메시지를 클래스로 디코딩 해야하는 오버 헤드는 일반적으로 가치가 없다는 것을 알았습니다.
operator >>
를 작성하는 대신 클래스에서 구현할 processMessage
수 있습니다. 그러면 C ++가 적절한 C ++처럼 보이고 C처럼 보이지 않게됩니다.
__packed__
구조체 를 사용해야 하고 엔디안 인식 ifdef 구현이 있어야합니다 (엔디안이 외부 데이터 소스와 반대되는 시스템에서 순서를 뒤집어 야 함) 제공하고 있습니다). 예쁘지는 않지만 임베디드 플랫폼의 원격 주변 장치에 대한 레지스터를 휴대용으로 패키징 / 언 패킹하는 데 사용했습니다.
char
유형이므로 앨리어싱이 면제 되기 때문에 여기서 앨리어싱은 문제가되지 않습니다 . 그러나 여전히 다른 문제가 있지만 여전히 문제가 있습니다. char*
해당 주소에서 이미 초기화 된 후자의 유형이없는 경우 수명 규칙을 위반하므로 UB입니다. Afaik은 대상 유형이 사소하게 구성 가능하더라도 C ++에서 메모리를 해당 유형으로 처리하는 데 공식적으로 메모리를 할당하는 것만으로는 충분하지 않습니다.
내부가 C ++ 인 라이브러리를 작성하고 있지만 C 또는 C ++ 코드로 API를 호출 할 수있는 경우 C ++에서 "struct"를 사용할 수 있습니다. C와 C ++ 코드 모두에 노출되는 구조체와 전역 API 함수를 포함하는 단일 헤더를 만들면됩니다.
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct foo
{
...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;
// Put your C API functions here
void bar(foo *fun);
#ifdef __cpp
}
#endif
그런 다음 C ++ 코드를 사용하여 C ++ 파일에 함수 bar ()를 작성하고 C에서 호출 가능하게 만들고 두 세계는 선언 된 구조체를 통해 데이터를 공유 할 수 있습니다. 물론 C와 C ++를 혼합 할 때 다른 경고가 있지만 이것은 간단한 예입니다.
Structs ( 보다 일반적으로 POD )는 언어 경계와 링커 형식간에 이식 가능하므로 C ++ 구현으로 C 호환 인터페이스를 제공 할 때 편리합니다.
그것이 당신에게 관심이 없다면, "class"대신에 "struct"를 사용하는 것이 의도의 좋은 전달 자라고 생각합니다 (@ZeroSignal이 위에서 말했듯이). Structs에는 예측 가능한 복사 의미가 있으므로 외부 미디어에 쓰거나 유선으로 전송할 데이터에 유용합니다.
Structs는 또한 의존적 인 typedef를 노출시키는 특성 템플릿과 같은 다양한 메타 프로그래밍 작업에 편리합니다.
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
... 그러나 그것은 실제로 구조체의 기본 보호 수준을 공개적으로 활용하는 것입니다 ...
다른 사람들이 지적했듯이
Stroustrup / Sutter의 사용시기에 대한 명확한 권장 사항이 있습니다.
클래스에 불변이있는 경우 클래스를 사용하십시오. 데이터 멤버가 독립적으로 다를 수있는 경우 구조체를 사용하십시오.
그러나 sth를 선언하는 것이 현명하지 않다는 것을 명심하십시오. 클래스 ( class X;
)로 정의하고 struct ( struct X { ... }
) 로 정의하십시오 . 일부 링커 (예 : g ++)에서 작동하고 다른 링커 (예 : MSVC)에서 실패 할 수 있으므로 개발자 지옥에서 자신을 찾을 수 있습니다.
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
것은 MSVC 2017을 컴파일하고 실행할 뿐 아니라 Foo
로 선언 struct
되었지만로 정의 된 명확한 경고를 생성합니다 class
. 그러나 나는 또한 어리석은 버그를 찾기 위해 우리 팀이 반나절을 소비했다는 것을 분명히 기억합니다. 그때 우리가 어떤 MSVC 버전을 사용했는지 잘 모르겠습니다.
class
struct
struct
에 -forwards class
-forwards을, 문제는 멀리 갔다. 오늘 현재도 이상하다고 생각합니다. 당신이 그것에 빛을 비출 수 있다면 기쁠 것입니다.
클래스 멤버는 기본적으로 비공개입니다.
class test_one {
int main_one();
};
에 해당
class test_one {
private:
int main_one();
};
당신이 시도하면
int two = one.main_one();
main_one is private
액세스 할 수 없기 때문에 오류가 발생 합니다. 공개를 지정하여 초기화하면 해결할 수 있습니다.
class test_one {
public:
int main_one();
};
구조체는 기본적으로 멤버가 공개되는 클래스입니다.
struct test_one {
int main_one;
};
수단 main_one
은 비공개입니다. 즉
class test_one {
public:
int main_one;
};
멤버가 어떤 가치를 가질 수있는 데이터 구조에 구조체를 사용하면 더 쉽습니다.
struct
오버 의 장점은 class
"첫 번째 공개 멤버, 그 다음 개인"을 고수하는 경우 한 줄의 코드를 저장한다는 것입니다. 이런 관점에서 나는 키워드가 class
쓸모 없다는 것을 알게 되었다.
다음은 only struct
and never 를 사용하는 또 다른 이유입니다 class
. C ++에 대한 일부 코드 스타일 지침은 함수 매크로에 작은 문자를 사용하는 것이 좋습니다. 그 이유는 매크로가 인라인 함수로 변환 될 때 이름을 변경할 필요가 없다는 것입니다. 여기도 마찬가지입니다. 멋진 C 스타일 구조체가 있고 언젠가 생성자 또는 편리한 메소드를 추가해야한다는 것을 알게되었습니다. 로 변경 class
하시겠습니까? 어디에나?
struct
s와 class
es를 구별하는 것은 너무 번거로워서 우리가해야 할 일을 프로그래밍하는 방식으로 들어가는 것입니다. 많은 C ++의 문제와 마찬가지로, 하위 호환성에 대한 강한 열망에서 비롯됩니다.
class
합니까? struct
키워드로 정의 된 클래스 는 멤버 함수 나 생성자를 가질 수 없다고 생각 했습니까 ?
joe()
로 정의해야 class
합니까? int
멤버가 4 명 이상인 모든 클래스는 struct
키워드 로 정의해야 합니까?
struct
되고 메소드가있는 집계는 class
" 로 정의됩니다 . 너무 번거 로움.
모두 struct
와 class
생각 가시성과 같은 다른 기본값으로 후드 동일하며, struct
기본은 공개와 class
기본값은 비공개입니다. 당신은 적절한 사용과 다른 될 중 하나를 변경할 수 있습니다 private
와 public
. 상속, 메소드, 생성자, 소멸자 및 객체 지향 언어의 모든 장점을 허용합니다.
그러나 둘 사이의 큰 차이점은 struct
키워드가 C에서 지원되는 반면 키워드는 C에서 지원 class
되지 않는다는 것입니다. 하나는를 사용할 수있는이 수단 struct
으로는 될 수있는 파일이 포함 #include
너무 오래 같이 중 C ++ 또는 C로 struct
일반 C의 스타일 struct
과에서 다른 모든 파일 즉 어떤 C ++와 같은 특정 키워드, C와 호환 포함 private
, public
아니오를 메소드, 상속 없음 등
AC 스타일 struct
은 C 스타일 struct
을 사용하여 인터페이스를 통해 데이터를주고받는 것을 지원하는 다른 인터페이스와 함께 사용할 수 있습니다 .
AC 스타일 struct
은 메모리 영역의 레이아웃을 설명하는 일종의 템플릿 (C ++ 템플릿이 아니라 패턴 또는 스텐실)입니다. 지난 몇 년 동안 C와 C 플러그인 (여기서는 Java, Python 및 Visual Basic)에서 사용할 수있는 인터페이스가 C 스타일과 호환되는 인터페이스 중 일부가 만들어졌습니다 struct
.
기술적으로 C ++에서는 모두 동일합니다. 예를 들어 구조체에 연산자가 오버로드 될 수 있습니다.
그러나 :
나는 여러 유형의 정보를 동시에 전달하고 싶을 때 구조체를 사용한다. 나는 "기능적"객체를 다룰 때 클래스를 사용한다.
도움이 되길 바랍니다.
#include <string>
#include <map>
using namespace std;
struct student
{
int age;
string name;
map<string, int> grades
};
class ClassRoom
{
typedef map<string, student> student_map;
public :
student getStudentByName(string name) const
{ student_map::const_iterator m_it = students.find(name); return m_it->second; }
private :
student_map students;
};
예를 들어, 여기 get ... () 메소드에서 구조체 학생을 반환하고 있습니다-즐기십시오.
struct를 언제 사용하고 언제 C ++에서 클래스를 사용하기로 하시겠습니까?
내가 사용하는 struct
내가 정의 할 때 functors
와 POD
. 그렇지 않으면을 사용 class
합니다.
// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
bool operator()(int first, int second)
{ return first < second; }
};
class mycompare : public std::binary_function<int, int, bool>
{
public:
bool operator()(int first, int second)
{ return first < second; }
};
std::binary_function<>
는 더 이상 사용되지 않으며 c ++ 17도 제거합니다.
C ++에서는 "struct"를 사용하지 않습니다.
고의적으로 혼동하지 않는 한 개인 멤버를 원할 때 구조체를 사용하는 시나리오를 상상할 수 없습니다.
구조체를 사용하는 것이 데이터가 어떻게 사용되는지에 대한 구문상의 표시 인 것 같지만 클래스를 만들고 클래스 이름이나 주석을 통해 명시 적으로 만들려고합니다.
예 :
class PublicInputData {
//data members
};
struct
클래스의 멤버가 기본적으로 공개 될 것이라고 이미 명시 적으로 선언하지 않습니까?