게시글
질문&답변
2024.11.18
2.9 함수 만들기
안녕하세요? 질문&답변 도우미 Soobak 입니다. Q. 1분 30초에 printf가 출력은 맞는데, 여기서 받아와서 추가로 하는 작업이 없으니 가정으로 그냥 없다고 하신걸까요?: '함수의 출력' 과 'printf() 의 기능인 화면에 글자를 출력하는 것' 을 혼동하신 것 같습니다.printf() 함수는 '화면에 글자를 출력' 하는 기능을 합니다.이 때, 이 기능을 수행하는 '함수' say_hello() 의 관점에서 생각해보면,단순히, printf("Hello, World!\n"); 라는 기능을 수행하고 추가로 진행하는 작업이 없으므로'함수의 입력과 출력' 이 없다고 가정하였던 것입니다.출력이 없는 함수는 문법적으로 반환형에 무치형(void)을 사용하고, 입력 또한 없는 함수이므로 매개 변수에 void 를 명시합니다.최종적으로 say_hello() 함수는 다음과 같이 printf("Hello, World!\n") 를 통해 화면에 글자를 출력하는 기능을 갖는 함수가 됩니다.void say_hello(void) // 반환형 void, 매개 변수 void { printf("Hello, World!\n"); } 혹시 이해가 어려우시다면, 강의 2.6 printf() 함수의 기본적인 사용법 의 1:45 부분 교수님 설명과 그림을 참고해보시면 바로 이해가 쉽게 되실 것입니다. Q. 2분1초에 출력으로 받을게 없으니까 출력 받는 void 라고 쓴다고 하셨는데, 여기서 출력으로 받을게 없다는것이 어떤건가요?: 위 질문 답변의 내용과 같은 맥락에서, 함수의 출력(반환하는 것)이 없는 상황을 의미합니다.위의 void say_hello(void) 함수처럼 단순하게, 함수 내부에서 기능을 수행하는 경우입니다. 간단하게 추가 설명을 드려보면, C언어는 함수의 출력(반환)과 입력에 대해서 데이터의 자료형을 명시해주어야 합니다.(자료형에 대해서는 이전 강의 2.4 자료형이 필요한 이유 를 참고해보셔도 좋고, 이어지는 섹션 4 데이터와 C언어 에서도 자세하게 학습하시게 됩니다.)예를 들어, 정수(integer)를 출력(반환)하는 함수의 경우에는 다음과 같이 작성됩니다.int doSomething(void) // 함수의 출력 - 정수, 입력 - 없음 { return 2; // 함수가 출력하는 것은 정수 자료형의 2 } int doSomething(int i) // 함수의 출력(반환) - 정수, 입력 - 정수 { return i + 2; // i 라는 정수 자료형 데이터를 입력받아 함수가 반환(출력)하는 것은 정수 자료형의 입력값 + 2 } 곧 이어서 자세히 학습하게 되실 내용이니,'함수의 출력' 과 '화면에 글자를 출력' 하는 것의 차이점, 그리고 함수가 출력하거나 함수에 입력하는 것이 없을 때 에는 void 를 사용한다는 것 정도만 이해해두시고 학습을 이어나가시는 것을 추천드립니다.
- 1
- 2
- 6
질문&답변
2024.11.14
예외 클래스 상속 관련 다른 예제 코드 확인 부탁 드립니다.
안녕하세요? 질문&답변 도우미 Soobak 입니다. 흥미로운 질문이시네요.다만, 제 환경에서는 첫 번째 코드 또한 정상적으로 동작합니다.dynamic_cast 도 정상적으로 잘 동작하여 자식 클래스에 있는 에러 코드를 잘 출력합니다.(사진)(실행 화면) 메모리 관련 검사 또한 해보았으나, 아쉽게도 문제가 없었습니다.(사진) 어떠한 문제가 발생한 것이신지 조금 더 구체적으로 알려주시면 제가 더 적절한 도움을 드릴 수 있을 것 같습니다.그럼에도 질문주신 내용에 대해서 답변을 드려보자면, 예외 객체를 동적으로 할당하여 throw 하는 경우는 예외가 적절히 catch 되지 않으면 메모리가 해제되지 않아 메모리 문제가 생길 수 있게 됩니다.또한, 예외를 관리하는 데에 어려움이 증가할 것 같습니다. 스택에서 직접 생성된 예외 객체는 예외가 포착되지 않더라도 자동으로 메모리가 해제되므로,개인적으로는 try 이후 catch 구문의 순서를 적절히 조절하는 것, 그리고 예외 객체를 던지고 받을 때 상속 구조를 유의하여 값-참조 자료형을 적절히 선택하고 관리하는 방향을 더 선호할 것 같습니다.개인적으로는 dynamic_cast 를 사용하지 않고, 다음과 같이 작성할 것 같습니다.#include #include class Exception { public: explicit Exception(const std::string& message) : message_(message) {} virtual ~Exception() {} virtual const char* what() const noexcept { return message_.c_str(); } private: std::string message_; }; class CustomException : public Exception { public: explicit CustomException(const std::string& message, int errorCode) : Exception(message), errorCode_(errorCode) {} int getErrorCode() const { return errorCode_; } private: int errorCode_; }; void throwException() { CustomException ex("CustomException occurred", 404); throw ex; } int main() { try { throwException(); } catch (const CustomException& e) { // CustomException을 직접 catch std::cout 다만, 추후 섹션 16 에서 학습하시게 되는 스마트 포인터를 이용하신다면 메모리 관리에 조금 덜 신경쓰며 동적으로 예외 객체를 할당하여 사용하는 방법도 있겠네요.하지만, 그럼에도 불구하고 여러가지 측면을 고려했을 때 개인적으로 예외 객체를 동적으로 할당하는 것은 지양하는 것이 좋다고 생각합니다.고민해볼 수 있는 재미있는 내용이네요. 항상 열정있는 학습과 재미있는 질문 감사합니다. 저에게도 좋은 자극이 되어 주시고 계십니다.궁금한 점이 있으시면 편하게 질문해주세요! 글을 통해서 대화를 나누는 역량 그 자체는 저도 열심히 신경쓰며 키워나가고 있는 부분이지만,질문의 내용이나 주제에 대해서는 궁금증이 생기실 때 편하게 작성해주시는 것이 좋은 것 같습니다.
- 1
- 2
- 33
질문&답변
2024.11.13
mingw-w64 수동설치
안녕하세요? 질문&답변 도우미 Soobak 입니다. sourceforge 에서의 최신 버전 압축파일이 설정하기 조금 어렵게 되어있네요.조금 더 설정하시기 편한 압축 파일의 링크 주소를 첨부드립니다.https://github.com/brechtsanders/winlibs_mingw/releases/download/13.3.0posix-11.0.1-msvcrt-r1/winlibs-x86_64-posix-seh-gcc-13.3.0-mingw-w64msvcrt-11.0.1-r1.zip (https://winlibs.com/ 페이지에서 하단의 MSVCRT runtime 항목의 Zip 압축파일 입니다.) 이후의 과정은 C:\Program Files\ 에 mingw64 라는 폴더를 위치시키셔서 압축을 해제하신 후해당 강의 4:10 부분 부터의 내용에 따라서 '환경 변수'(Path)를 설정해주시면 됩니다.환경 변수를 설정하실 때에는 C:\Program Files\mingw64\bin 을 입력해주시면 됩니다. 개인적으로, 처음 학습하실 때에는 환경 설정이 복잡하다고 느껴지실 수 있으니 보다 편리한 Visual Studio 를 사용하시는 것을 추천드립니다. (Visual Studio 와 Visual Studio Code 는 다른 프로그램입니다.)
- 1
- 2
- 18
질문&답변
2024.11.11
연산자의 내부적인 작동 원리가 궁금합니다
안녕하세요? 질문&답변 도우미 Soobak 입니다. 연산자 자체에 자료형을 인지하고 판단하는 명령이 있다고 보기 보다는,컴파일러가 연산을 수행하는 변수의 자료형에 따라서 적절한 형변환을 진행한 후 연산을 수행한다는 것이 더 알맞은 표현 같습니다.C++ 언어에서는 연산자 오버로딩을 통해서 자료형에 따라 다른 동작을 하도록 명시적으로 정의할 수 있습니다.
- 1
- 2
- 20
질문&답변
2024.11.11
string data가 어느 메모리 영역에 저장 되는지 헷갈려서요..
안녕하세요? 질문&답변 도우미 Soobak 입니다. 일반적으로 읽기 전용 데이터 세그먼트에 저장됩니다.강의 12:08 부분의 화면에 첨부된 설명과,이어지는 강의 중 16:20 부분에서 동일한 문자열 리터럴을 다루는 예제를 참고해보시면 학습에 도움이 되실 것 같습니다.
- 1
- 2
- 20
질문&답변
2024.11.09
후속 강의 수강권 문의
안녕하세요? 질문&답변 도우미 Soobak 입니다. https://blog.naver.com/honglabcokr/221747419352위 링크의 교수님 안내 글을 참고하시어 신청 부탁드립니다.
- 1
- 2
- 28
질문&답변
2024.11.06
Template한 A클래스의 생성자에 const T& input 부분 질문 있습니다.
안녕하세요? 질문&답변 도우미 Soobak 입니다. 혹시나 해서, 제 환경(Windows&MSVS2022)에서 Debug, Release 모드 변경, 최적화 수준 변경 등 여러가지 시도를 해보며 질문자님의 문제를 재현해보려 했지만 계속 정상적으로 동작이 되네요. 😭컴파일러와 운영체제도 변경해보며 테스트해보았지만 잘 동작합니다.& 참조자를 제거하고 해결되셨으니, 참조 과정에서 문제가 생긴 것은 맞아보입니다.혹시, 이전에 주신 질문과 연관지어서 이전 강의를 학습하시며 생성하신 파일들 중 '템플릿화 된 클래스 A'가 있는 파일을 같이 빌드하신 것은 아니신지, 헤더 파일 분리 혹은 프로젝트 종속성을 통해 확인해보시면 좋을 것 같습니다.혹시 해결이 안되신다면 다른 문제의 원인이 무엇일지 꾸준히 찾아보고 말씀드리겠습니다.
- 1
- 2
- 25
질문&답변
2024.11.06
13.4 char형 특수화 템플릿을 추가한 뒤로
안녕하세요? 질문&답변 도우미 Soobak 입니다. 코드에는 문제가 없으십니다.첨부 사진을 자세히 살펴보니, 파일 Template13-1.obj 와 파일 Template13-4.obj 두 개의 오브젝트 파일에서 템플릿 함수가 중복 정의되어 링킹 오류가 발생하는 것이네요.아마, 열심히 학습하시는 과정에서 이전 13.1 함수 템플릿 강의 중 작성하신 파일의 템플릿 함수가 이번 강의의 템플릿 함수와 충돌하는 것 같습니다.해당 강의(13.4 함수 템플릿 특수화)의 후반부에서 교수님께서 설명해주시는 내용 중 템플릿 함수와 '헤더'에 대해서 다루시는 부분을 참고해보시면 문제 해결에 도움이 되실 것 같습니다.혹은, 컴파일 환경을 수정하여 이전 강의에서 작성하신 파일과 충돌을 일으키지 않도록 종속성을 해결하는 방법도 있습니다.꼼꼼히 한 단계, 한 단계 강의를 수강하시는 과정에서 발생한 문제를 질문주신 것이 느껴짐과 동시에,이를 통해 해당 섹션(템플릿)에서 중요한 내용 중 하나인 '헤더 파일' 을 통해 관리하는 부분에 대해서 직접 문제를 겪어보시며 학습하게 되신 것 같아 인상 깊네요.만약, 혹시 해결에 어려움이 있으시면 프로젝트의 구성 환경(솔루션, 파일 구성 등)을 알려주세요.제가 조금 더 구체적으로 도움을 드릴 수 있을 것 같습니다.항상 좋은 질문과 피드백 말씀 감사드립니다.
- 1
- 1
- 17
질문&답변
2024.11.03
컨테이너 클래스 피드백 부탁드립니다.
안녕하세요? 질문&답변 도우미 Soobak 입니다. 과제에서 명시적으로 요구된 내용에서 더 나아가 복사 생성자와 대입 연산자오버로딩까지 챙기며 구현하려 하신 부분이 훌륭하시네요.다만, 이 과정에서 조금 아쉬운 부분이 있는 것 같습니다.우선, 복사 생성자에서 메모리 할당이 누락되어 있어 복사 과정에 오류가 발생하게 됩니다.IntArray(const IntArray& copy) :m_length(copy.m_length) { for (int i = 0; i : m_data 는 메모리의 할당되어있지 않기 때문에 오류가 발생합니다. 또한, 대입 연산자 오버로딩에 있어서 매개변수의 자료형과 반환 자료형이 값으로 되어있는 부분도참조로 변경하시는 것이 좋습니다. 불필요한 복사 문제와 자기 대입 시 메모리 관리가 엉키는 문제 등을 방지하기 위함입니다.복사 생성자를 사용하는 코드를 추가하여 프로그램을 실행시켜 보시면 바로 문제점을 쉽게 파악하실 수 있으실 것 같습니다.(만약, 이해가 어려우시면 강의 9.11 대입 연산자 오버로딩, 깊은 복사, 얕은 복사 부분 를 참고해보시면 도움이 되실 것 같습니다.)나머지 부분은 잘 구현하셨습니다.반복문을 많이 사용하시는 부분을 걱정하셨지만, 지금의 학습 단계에서 훌륭하게 작성하셨다고 생각합니다.추후에 다양한 알고리듬과 자료구조를 학습하시면서 더욱 발전하실 수 있으실 것 같습니다. 추가적으로, 더 나은 방법에 대해 궁금증을 갖고 계신 것 같으셔서, 생각난 재밌는 내용을 간단히 소개드려봅니다.: 컴파일러마다 구현 내용은 조금씩 다르지만, 데이터 추가 가능성이 있는 컨테이너의 경우 최초, 혹은 resize() 를 통한 메모리 할당을 '명시된 크기' 보다 조금 더 많이 할당을 해놓습니다.따라서, push_back() 혹은 insert() 과정에 있어서 이미 할당된 메모리 공간이 충분하다면 매번 '추가되는 데이터의 개수' 만큼 메모리 할당을 진행하지 않고, 비어있는 메모리 공간에 값을 추가합니다.그러다가, 비어있는 메모리 공간이 더 이상 없는 경우 또 여유롭게 메모리 할당을 진행합니다.얼마나 여유롭게 메모리를 할당할지는 컴파일러마다 다르고, 이 과정에 있어서 현재 힙에 할당이 가능한 메모리 공간이 충분한지도 체크하여 예외를 처리하는 등 재미있지만 조금 복잡한 과정 등으로 STL 의 컨테이너들이 구현되고는 합니다. 이외에도 효율성, 최적화를 위해 참 신기하게 구현된 부분이 많으니, 추후 여유가 되신다면 g++ 혹은 clang 등의 컴파일러에서 구현된 STL 의 컨테이너 클래스를 들여다보시는 것도 좋은 학습이 되실 것 같습니다.응원합니다!
- 1
- 1
- 19
질문&답변
2024.10.31
Virtual Table에 관해 질문 있습니다.
안녕하세요? 질문&답변 도우미 Soobak 입니다.항상 꼼꼼히, 적극적으로 학습하시는 모습이 인상깊네요.질문주신 내용들에 대해서 정리하여 답변 드립니다.각 클래스는 자신만의 가상함수표를 가지게 됩니다.이 때, 질문자님의 디버거에서 '자식 객체의 가상함수표' 만 보이는 이유는 현재 디버깅 중인 객체가 자식 객체이기 때문입니다. (혹시, 혼동이 되신다면 해당 강의 2:15 부분의 강의 화면과 3:45 부분의 강의 화면에서 VTable 을 비교해보시면 이해에 도움이 되실 것 같습니다.) 또한, 가상함수표에 일반 함수가 있는 것은 아닙니다. 가상 함수만 가상함수표에 포함됩니다.이전 강의에서 학습하신 내용처럼, 일반 함수는 컴파일 시점에 정적으로 바인딩됩니다. 편의를 위해 디버깅 도구에서 가상함수표 정보와 함께 보여질 수는 있지만, 실제 가상함수표의 일부가 아닙니다.vfptr 은 가상함수표의 시작을 가리키는 포인터이고, 가상함수표의 각 항목은 실제 함수의 메모리 주소를 가리킵니다. 하지만, 이 과정에 대한 컴파일러 최적화로 인해서 디버깅 도구를 통해 살펴보시는 함수의 주소가 달라질 수 있습니다. 이에 대해서는 virtual thunk 라는 키워드로 검색을 해보시면 도움이 되실 것 같습니다.하지만, 지금 단계에서는 충분히 꼼꼼히 공부를 잘 하고 계시니, 핵심 내용만 이해를 하셨다면 이어서 학습을 하시는 것을 추천드립니다. 간단하게 핵심 내용을 정리 드려보면,각 클래스는 자신만의 가상함수표를 가지며, 이 표에는 일반 함수가 아닌 가상 함수만이 포함됩니다.이 때, 가상함수표의 각 항목은 실제 함수의 주소를 가리킵니다.가상함수 호출시에는 객체의 vptr 을 이용하여 해당 클래스의 가상함수표에 접근하며,접근한 표에서 해당 함수의 실제 주소를 찾아 함수를 실행하게 됩니다.꾸준히 질문을 주셔서 감사하고 반갑습니다. 응원 많이 하고 있습니다.
- 1
- 1
- 17