C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source>g++ -o RacingCar.cpp Car.cpp

 

틈틈히 C++ 를 공부해놔야할 것 같아 정리하는 문서입니다.

 

교재는 『윤성우의 C++ 열혈프로그래밍』를 사용하였고, 예제를 통해 실습 진행해보았습니다.

 

환경설정은 기존에 C언어를 공부하면서 설치했던 MinGw를 이용했습니다.

(MinGw에 C언어, C++언어 컴파일러 둘 다 탑재하고 있음)

 

 

 

기존에 해놓은게 있어서, 환경변수를 따로 건드린 것은 없었습니다.

 

또한, vscode 를 오랜만에 쓰려니, 단축키가 계속 헷갈려서 intellij keymap을 extension으로 설치하였습니다.

 

(Pycharm의 제작회사가 Intellij임)

 

 

 

살짝 다른 부분들이 있지만, 그래도 대부분(70~80%) 정도는 지원해주는 것 같아 큰 불편함 없이 적응했습니다.

 

포인터와 구조체 사용방법은 아직 완벽하게는 아니지만, 어느정도 숙지하고 책의 예제를 따라쳐보면서, 익숙해지는 시간을 가졌습니다.

 

C언어에서는 구조체에서 Attribute만 사용할 수 있는 불완전한 상태였는데,

 

C++로 넘어오면서, class가 사용가능해지고, 함수도 선언가능해졌습니다.

 

또한, Python에서는 "from somefilename import ClassName" 면 쉽게 다른 파일의 클래스를 사용할 수 있었지만,

 

C++로 들어오면서는 헤더파일의 이해와, #ifndef, #define, #endif, namespace의 개념에 대해 이해가 필요했습니다.

 

책에서 선언한 Car class 입니다.

 

/* Car.h */

#ifndef __CAR_H__
#define __CAR_H__

namespace CAR_CONST {
enum {
    ID_LEN = 20,
    MAX_SPD = 200,
    FUEL_STEP = 2,
    ACC_STEP = 10,
    BRK_STEP = 10
};
}

class Car {
   private:
    char gamerID[CAR_CONST::ID_LEN];
    int fuelGuage;
    int curSpeed;

   public:
    void InitMembers(char* ID, int fuel);
    void ShowCarState();
    void Accel();
    void Break();
};

#endif

 

/* Car.cpp */
#include "Car.h"

#include <cstring>
#include <iostream>
using namespace std;

void Car::InitMembers(char* ID, int fuel) {
    strcpy(gamerID, ID);
    fuelGuage = fuel;
    curSpeed = 0;
}

void Car::ShowCarState() {
    cout << "소유자ID: " << gamerID << endl;
    cout << "연료량: " << fuelGuage << "%" << endl;
    cout << "현재 속도: " << curSpeed << "km/s" << endl;
}

void Car::Accel() {
    if (fuelGuage <= 0) {
        return;
    } else {
        fuelGuage -= CAR_CONST::FUEL_STEP;
    }

    if (curSpeed + CAR_CONST::ACC_STEP >= CAR_CONST::MAX_SPD) {
        curSpeed = CAR_CONST::MAX_SPD;
        return;
    }
    curSpeed += CAR_CONST::ACC_STEP;
}

void Car::Break() {
    if (curSpeed < CAR_CONST::BRK_STEP) {
        curSpeed = 0;
        return;
    }
    curSpeed -= CAR_CONST::BRK_STEP;
}
/* RacingMain.cpp */
#include "Car.h"

int main() {
    Car run99;
    run99.InitMembers("run99", 100);
    run99.Accel();
    run99.Accel();
    run99.Accel();
    run99.ShowCarState();
    run99.Break();
    run99.ShowCarState();
    return 0;
}

 

이렇게 작성하고 Build 를 실행했더니 다음과 같은 오류를 만났다.

Car.cpp 에서 세부적으로 선언한 함수들이 다 undefined 처리가 되었다.

 

빌드를 시작하는 중...
"C:\Program Files\mingw64\bin\g++.exe" -fdiagnostics-color=always -g C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source\RacingMain.cpp -o C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source\rooster.exe
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccrwiMAk.o: in function `main':
C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:6: undefined reference to `Car::InitMembers(char const*, int)'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:7: undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:8: undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:9: undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:10: undefined reference to `Car::ShowCarState()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:11: undefined reference to `Car::Break()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/KDT107/Desktop/learn_cpp/init_folder/cpp_source/RacingMain.cpp:12: undefined reference to `Car::ShowCarState()'
collect2.exe: error: ld returned 1 exit status

빌드가 완료되었지만, 오류가 발생했습니다.

원인을 찾아보니 g++로 컴파일 할 때 다음과 같이 터미널에 작성해줘야한다는 것이다.

C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source>g++ -o Car.cpp RacingCar.cpp

그런데 실수로 순서를 바꿔서 넣었더니..

C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source>g++ -o Car.cpp RacingMain.cpp
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x22): undefined reference to `Car::InitMembers(char const*, int)'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x2e): undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x3a): undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x46): undefined reference to `Car::Accel()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x52): undefined reference to `Car::ShowCarState()'        
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x5e): undefined reference to `Car::Break()'
c:/program files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\KDT107\AppData\Local\Temp\ccao3DhY.o:RacingMain.cpp:(.text+0x6a): undefined reference to `Car::ShowCarState()'        
collect2.exe: error: ld returned 1 exit status

 

또 undefined 에러가 나왔다.

 

어떤 것을 먼저 참조시키느냐가 순서가 중요해진다는 걸 알았다...

 

순서를 옳게 했더니 잘 compile 되었다.

 

하지만, 터미널에서 매번 입력하는 것보단 vscode 에서 ctrl + F5 로 run 하고 싶었다.

 

방법을 찾아보니 StackOverFlow에 비슷한 상황이 있었다.

https://stackoverflow.com/questions/72843254/vscode-compile-c-with-external-classes-undefined-reference-to-myclassmycl

 

VSCode compile C++ with external classes - undefined reference to `MyClass::MyClass()'

Error when compiling my main file & external Class file using VScode. file structure: project/ --main.cpp --MyClass.cpp --MyClass.h MyClass.h #ifndef MY_CLASS_H #define MY_CLASS_H class My...

stackoverflow.com

 

#include "Car.cpp"
#include "Car.h"

int main() {
    Car run99;
    run99.InitMembers("run99", 100);
    run99.Accel();
    run99.Accel();
    run99.Accel();
    run99.ShowCarState();
    run99.Break();
    run99.ShowCarState();   
    return 0;
}

#include 에 참조가 필요한 cpp file을 추가해줌으로써 추가 terminal command를 작성할 필요 없이 run이 정상적으로 되었다.

소유자ID: run99
연료량: 94%
현재 속도: 30km/s
소유자ID: run99
연료량: 94%
현재 속도: 20km/s

또한, 개발 중간에

 

 
C:\Users\KDT107\Desktop\learn_cpp\init_folder\cpp_source\RacingMain.cpp:6:23: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    6 |     run99.InitMembers("run99", 100);
      |                       ^~~~~~~

빌드가 완료되었지만, 경고가 발생했습니다.
 *  터미널이 작업에서 다시 사용됩니다. 닫으려면 아무 키나 누르세요.

 

이런 경고가 발생했었는데, 원인은 Cpp 의 char * -> const char * 로 선언이 필요했다.

 

StackOverFlow에 확인해보니,

https://stackoverflow.com/questions/20944784/why-is-conversion-from-string-constant-to-char-valid-in-c-but-invalid-in-c

 

Why is conversion from string constant to 'char*' valid in C but invalid in C++

The C++11 Standard (ISO/IEC 14882:2011) says in § C.1.1: char* p = "abc"; // valid in C, invalid in C++ For the C++ it's OK as a pointer to a String Literal is harmful since any attempt to modify...

stackoverflow.com

 

기존에는 암시적으로 const char* 로 바꾸는 작업을 해줬는데, C++ 11버전으로 바뀌면서, 직접 형변환을 하지 않으면 경고를 날리게 되었다고 한다. 기존의 코드들은 작동하게끔 유지해야할 필요가 있어서 build는 되지만 안전하게 string을 parameter로 사용할 경우엔 const char* 를 사용하도록 한다.

 

Python class 에서 Cpp class를 선언해보는 과정을 겪어보았는데, 확실히 python에서 parameter에 제한이 없는 상태로 코딩하다가, 보다 엄격한 문법 규칙을 준수하다보니, 답답함과 뭔가 생산성의 저하..? 가 느껴졌다.

 

하지만, 그만큼 파이썬에서 이런 일련의 과정을 내부적으로 하고 있던 일이고, Python으로 prototype을 제작하고, Cpp로 본격 개발을 하는 경우가 많다고 하니, 두 언어 모두 결과적으로 숙련되어야할 숙명이라 생각한다.

 

틈틈히 Cpp 개발을 공부하여 익숙해져보도록 노력할 예정이다.

 

감사합니다.

 

+ Recent posts