C++
04. 클래스와 객체
til_t
2021. 1. 27. 22:34
클래스와 객체
< ex01_class.cpp >
#include <iostream>
#include <string>
using namespace std;
class Circle{
public:
int radius;
string color;
double calcArea(){ // 파이썬과 달리 self 매개 변수 없다
return 3.14 * radius * radius;
}
};
int main(int argc, char const *argv[])
{
Circle obj; // 객체 생성
obj.radius = 100;
obj.color = "blue";
// c++은 고정시키고 사용
// obj.area = 40; // 에러 -- 동적으로 멤버 추가 불가
cout << "area : " << obj.calcArea() << endl;
return 0;
}
- c++를 사용하는 궁극적인 목표 -> 클래스를 사용하기 위함
- 멤버 (멤버변수(데이터), 멤버함수(메서드))
- 클래스 - 객체(인스턴스)의 형태를 정의하는 설계도
-
객체(인스턴스) - 클래스의 형태를 취하는 실체
-
클래스 정의
- class 클래스 이름{ // 클래스 이름은 파스칼 표기법
- 자료형 멤버변수;
- // 변수도 고정시켜서 사용
- 반환형 멤버함수(); // 메서드
- };
-
객체 생성
-
클래스명 객체명; -> 스택에 만들어진다, 인스턴스는 스택에 위치한다, 정적할당, 선언과 동시에 메모리가 잡힌다 (지역변수면 스택에 만들어진다) ex) Circle obj;
-
정적할당 -> 스택, 동적할당 -> 힙
-
지역변수와 같이 선언한다, 함수가 끝날 때 사라진다는 것도 같다, 다른 점은 정적할당인가 동적할당인가의 차이이다
- 파이썬의 인스턴스는 힙에 만들어진다 (c = Circle())
- 파이썬에서 정적할당은 숫자와 bool 밖에 없다, 나머지는 동적할당으로 힙에 생긴다
-
-
객체 멤버 접근 (접근 지정자에 따라 다르다)
- . 연산자로 접근 ex) obj.radius = 3;
-
접근 지정자
- private (비공개), 클래스 안에서만 접근, 사용 가능
- protected (비공개), 상속에서 사용
- public (공개), 어디서나 접근 가능
- 보통 멤버변수는 private, 메서드는 public으로 운영한다
-
c++에는 가비지 컬렉터가 없다! -> 힙에 있는 메모리를 지우는 일은 개발자의 책임
< ex03_car.cpp >
#include <iostream>
#include <string>
using namespace std;
class Car{
public:
int speed;
int gear;
string color;
void speedUp(){
speed += 10;
}
void speedDown(){
speed -= 10;
}
};
int main(int argc, char const *argv[]) {
Car myCar;
myCar.speed = 100;
myCar.gear = 3;
myCar.color = "red";
myCar.speedUp();
myCar.speedDown();
return 0;
}
< ex04_overload.cpp >
#include <iostream>
#include <string>
using namespace std;
class PrintData{
public:
void print(int i){ cout << i << endl;}
void print(double f){ cout << f << endl;}
void print(string s = "No Data!"){ cout << s << endl;}
// 함수 명은 같지만 매개변수가 다르다, 다 다른 함수
};
int main(int argc, char const *argv[]) {
PrintData prn;
prn.print(1);
prn.print(3.14);
prn.print("C++ is cool");
prn.print();
return 0;
}
-
객체 지향의 특징
-
캡슐화
- 묶어서 관리한다, 관리해야 하는 데이터와 데이터를 이용한 함수가 클래스로 묶여있다
-
정보 은닉
- 정보를 숨기겠다, 접근제한자를 통해서 정보를 숨길 지 공개할 지 선택할 수 있다
-
상속과 다형성
- 부모의 내용을 자식이 받아서 사용하는 것
- 다형성 -> 형태가 많다라는 뜻
-
-
상속
- class 자식 클래스 명: public 부모 클래스 명{
- }
- public이면 public으로 가져오겠다, private라면 부모클래스에 있는 모든 접근제한자가 private로 바뀌어서 상속받는다
< ex05_inherit.cpp >
#include <iostream>
using namespace std;
class Shape{
protected:
// private로 했을 땐, x, y는 상속되지 않았을 것
// 외부에는 공개하지 않으면서 상속은 되게 하는 것이 protected의 역할
int x, y;
public:
void draw(){}
void move(){}
};
class Rectangle: public Shape{
protected:
int width, height;
public:
int calcArea(){
return width * height;
}
};
- 헤더와 cpp파일을 구분하지 않고 하나의 파일에 다 넣으면 관리하기가 힘들어진다
- class 하나당 파일을 하나로 정의한다
-
클래스 원형과 구현 정의 분리
-
헤더 파일에 클래스 원형
- 멤버 변수 정의
- 멤버 함수의 원형 정의
-
cpp 파일에 멤버 함수 정의
- 헤더 파일을 먼저 include
-
- c++에서는 변수와 함수 중복시 듀플리케이트 에러가 난다
- 중복되는 것을 피하기 위해서 함수 원형을 헤더에 남기고 실제 함수 정의 코드는 정의파일에 남긴다
- easy c++ projects 확장팩 설치
- 디렉토리 새로 오픈
- F1 -> create new c++ project -> linux
- F1 -> create new class constructor
- 컴파일하고 싶으면 터미널에 make
- 실행하고 싶다면 터미널에 bin/main.exe
< include/Car.hpp >
#pragma once
#include <string>
using namespace std;
// 헤더 파일
// 클래스 원형
class Car {
// 디폴트 접근 제한자 : private
int speed;
int gear;
string color;
public:
int getSpeed(); // 함수 원형
void setSpeed(int s);
};
< include/PrintData.hpp >
#pragma once
#include <string>
using namespace std;
class PrintData{
public:
void print(int i);
void print(double f);
void print(string s = "No Data!"); // 초기값 배정 (헤더파일에서만 해주면 된다)
};
< src/Car.cpp >
#include "Car.hpp" // "" 검색 순서 : cwd(와 include 검색) -> 사용자 lib -> 컴파일러 lib
#include <iostream> // <> 검색 순서 : 사용자 lib -> 컴파일러 lib
// 메서드임을 나타내기 위해 :: 스코프 연산자 쓴다, 어디 소속인지
void Car::setSpeed(int s){
speed = s;
// 지역변수 speed X, 멤버변수 speed
}
int Car::getSpeed(){
return speed;
}
< src/PrintData.cpp>
#include "PrintData.hpp"
#include <iostream>
void PrintData::print(int i){
cout << i << endl;
}
void PrintData::print(double f){
cout << f << endl;
}
void PrintData::print(string s){ // 디폴트 값 지정은 헤더파일에서만 지정
cout << s << endl;
}
< src/main.cpp >
#include <iostream>
#include <string>
#include "Car.hpp"
#include "PrintData.hpp"
using namespace std;
void printCar(Car car){
cout << car.getSpeed() << endl;
car.setSpeed(20);
}
int main(int argc, char const *argv[])
{
Car myCar;
myCar.setSpeed(100);
printCar(myCar); // call by value
cout << "speed : " << myCar.getSpeed() << endl;
PrintData pd;
pd.print(10);
pd.print(10.2);
pd.print("Hello World");
pd.print();
return 0;
}
< Makefile >
CXX := g++
CXX_FLAGS := -Wall -Wextra -std=c++17 -ggdb
BIN := bin
SRC := src
INCLUDE := include
LIB := lib
LIBRARIES :=
EXECUTABLE := main
all: $(BIN)/$(EXECUTABLE)
run: clean all
cls
./$(BIN)/$(EXECUTABLE)
$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp
$(CXX) $(CXX_FLAGS) -I$(INCLUDE) -L$(LIB) $^ -o $@ $(LIBRARIES)
clean:
-del $(BIN)\*