[c++] 구조체 string 선언 오류

머그잔@Naver의 이미지

제가 c++ 공부하다가 오류가 있어 질문드립니다. 제공된 참고 소스는 문제 없는데 제가 직접 해 본 구조체 내부 string선언에서 오류가 있습니다.

[A.h]
struct StudentInfo
{
	string sName; //오류 발생
	int nNo;
	int nKorean;
	int nEnglish;
	int nMath;
	float fAve;
};
....
 
[A.cpp]
#include "stdafx.h"
#include "A.h"
#include "B.h"
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
 
...
StudentInfo* sInfo = new StudentInfo;
 
cout<< sInfo->sName << endl;
 
.....
 
[main.cpp]
#include "stdafx.h"
#include "A.h"
#include "E.h"
#include <iostream>
using namespace std;
 
.......

[오류내용]

오류 C3646 'sName': 알 수 없는 재정의 지정자입니다.
오류 C4430 형식 지정자가 없습니다. int로 가정합니다. 참고: C++에서는 기본 int를 지원하지 않습니다.

단지 선언인데 이런 오류가 나는 이유는 무엇일까요?
복잡한 구조가 아니라 include 중복은 아닌것 같은데요.

VS 2015버젼을 쓰고 있습니다

도움을 기다립니다.

lalupo20의 이미지

아니라면 죄송합니다.

머그잔@Naver의 이미지

인클루드 안해도 될겁니다.

저 프로젝트는 구현파일에 모든 인클루드가 포함되어 있습니다.

머그로 커피한잔

 의 이미지

아뇨.

C++는 선언의 순서에도 매우 민감한 언어입니다.

질문자님의 코드 A.cpp에서 A.h가 string보다 먼저 include됐다는 점을 생각해 보면, 아래와 같은 코드와 비슷하겠지요.

struct dummy{
        string member;
};
 
#include <string>
using namespace std;
 
// Something

직접 해 보시면 아시겠지만 컴파일되지 않습니다. string을 쓰려면 그 전에 string을 선언해야만 하고, 그게 string 헤더의 역할이지요.
소위 "전방 선언"만으로 해결되는 경우도 있습니다만, string 클래스는 사실 약간 복잡한 template의 instantiation이기도 하고,
표준 라이브러리 클래스에 대해서는 그냥 표준 헤더를 인클루드하는 게 제일 나은 방법입니다.

다시 말해서, A.h 앞에 #include <string>을 붙이셔야 한다는 말씀입니다.
여기서 짚고 넘어갈 점이 두 군데 있는데요

Q) 그러면 A.cpp에서는 string 헤더가 두 번 include되지 않는가?
A) 네, 그렇습니다. 그리고 그렇게 해도 별 문제 없습니다. 별 문제 없도록 표준 헤더들이 쓰여져 있어요.

Q) A.h에 using namespace std;을 써도 되는가?
A) 가능하기는 합니다. A.cpp에서도 using namespace std;를 넣는 바람에 두 개 들어가게 되더라도 컴파일은 됩니다.
그러나 별로 좋은 생각은 아닙니다. A.h를 포함하는 모든 소스 코드에 using namespace std;가 들어가잖아요.
일반적으로 사람들은 헤더 파일을 포함시켰을 때 자동으로 그게 들어갈 거라고 생각하지는 않습니다.

결과적으로 보면, 질문자님의 A.h 코드는 아래와 같이 고치면 문제가 없어질 겁니다.

// [A.h]
#include <string> // 헤더를 포함시킨다.
// using namespace std; 는 보통 헤더에서 쓰지 않음.
 
struct StudentInfo
{
        std::string sName; // 이 시점에선 using namespace std;가 없으므로
        int nNo;           // 부득이 string 앞에 std를 붙여 줌.
        int nKorean;
        int nEnglish;
        int nMath;
        float fAve;
};
 
// ....
머그잔@Naver의 이미지

정말 상세한 설명이라 감동입니다.

그런데 제가 연관해서 궁금한것이 있습니다.

[A.cpp]
#include "stdafx.h"
#include <string> //이동 위치
#include "A.h"
#include "B.h"
//#include <string> 원래 위치
#include <iostream>
#include <iomanip>
 
using namespace std;

저도 include 순서가 잘못되었다고 생각해서 위와 같이 해서 빌드 해보았습니다만
같은 빌드 오류가 발생하더군요. 주말내내 이것저것 삽질만 했네요.

설명해 주신데로 하면 저렇게 include순서만 바꾸었을때 빌드가 되어야 하는것이 아닌지 하는
궁금증이 있습니다. 이것도 답변해 주실수 있으실까요?

그리고 제가 보고 있는 책은 소스를 제공하는데 그 소스를 빌드 할때는 include순서가 제가 올린것과
같은데 빌드가 되더라구요. 그것도 참 의문입니다. 답변 주신데로면 책의 소스도 빌드가 안되어야 하는것
갈은데 말입니다.

머그로 커피한잔

 의 이미지

A.h 안의 stringstd::string로 바꾸세요.

헤더 부분은 using namespace std; 이전에 있고, 그렇다고 헤더에 using namespace std;을 쓰지도 않기 때문에 반드시 std::을 써 주어야 합니다. 제가 QnA 형식으로 써 드렸을 텐데요.

A.h 안에 string 말고 다른 표준 라이브러리 클래스를 쓰고 있다면 그것도 이런 식으로 바꿔 줘야 합니다.

질문자님께서 보고 계신 책이 뭔지도 모르고 어떤 코드인지도 모르니 책에 있는 코드가 어떻게 빌드되는지는 알려 드리기 어렵네요.

머그잔@Naver의 이미지

귀찮아도 답변 계속 해 주셔서 감사합니다.

제가 보고있는 책에 첨부된 예재 소스를 첨부하겠습니다.
뇌를 자극하는 c++이 제가 보고 있습니다.

이 예제의 students.cpp, students.h가 제가 처음 질문드린 상태인데
제가 참고해서 새롭게 만들었을때는 빌드 오류가 났습니다.
그래서, 답변 주신데로 수정하면 잘 빌드되는데 원래 예제는 비주얼스튜디오에 불러들여서
수정안해도 빌드가 잘되길래 차이가 궁금한 것입니다.

댓글 첨부 파일: 
첨부파일 크기
Package icon Ver2_3.zip10.4 KB

머그로 커피한잔

 의 이미지

그대로 압축 풀어서 빌드해봤습니다.
안 되는데요.

1>------ 빌드 시작: 프로젝트: 157361, 구성: Debug x64 ------
1>students.cpp
1>kldp\157361\students.h(8): error C3646: 'name': 알 수 없는 재정의 지정자입니다.
1>kldp\157361\students.h(8): error C4430: 형식 지정자가 없습니다. int로 가정합니다. 참고: C++에서는 기본 int를 지원하지 않습니다.
1>kldp\157361\students.cpp(31): error C2039: 'name': 'Student'의 멤버가 아닙니다.
1>kldp\157361\students.h(6): note: 'Student' 선언을 참조하십시오.
1>kldp\157361\students.cpp(70): error C2039: 'name': 'Student'의 멤버가 아닙니다.
1>kldp\157361\students.h(6): note: 'Student' 선언을 참조하십시오.
1>menu.cpp
1>main.cpp
1>kldp\157361\students.h(8): error C3646: 'name': 알 수 없는 재정의 지정자입니다.
1>kldp\157361\students.h(8): error C4430: 형식 지정자가 없습니다. int로 가정합니다. 참고: C++에서는 기본 int를 지원하지 않습니다.
1>list.cpp
1>코드를 생성하고 있습니다...
1>"157361.vcxproj" 프로젝트를 빌드했습니다. - 실패
========== 빌드: 성공 0, 실패 1, 최신 0, 생략 0 ==========
머그잔@Naver의 이미지

정말 친절하신 답변 감사합니다.

제가 초보라 빌드가 원하는것이 안되고 다른것이 되나봅니다.
예제가 여러버전이 섞여 있어서 그런가 봅니다.

제공된 예제는 왜 안되는 것을 제공했는지..

다시 한번 정말 감사드립니다.

머그로 커피한잔

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.