static(정적 변수), const&/*, 포인터 연산, 배열-포인터 관계(arr[i] == *(arr+i))public/private/protected), 멤버(변수/함수): member(value)), thisstd::cout/cin, << >>, std::endl, == vs =, += vs =+virtual, 동적 바인딩(가상 테이블 개념), 포인터/참조 업캐스팅, 순수 가상 함수(=0). vs -> : 객체 멤버 접근은 ., 포인터로 멤버 접근은 -> :: : 클래스 밖에서 멤버함수 구현할 때 Student::getAvg() & / * : 주소 얻기 / 역참조(포인터 값 접근), 배열-포인터 관점의 핵심 } << / >> : cout 출력, cin 입력(스트림 방향) = vs == : 대입 vs 비교(조건문에서 가장 많이 터짐) += vs =+ : 누적 더하기 vs “그냥 +값 대입” =0 : 순수 가상 함수(추상 클래스) : member(value)(멤버 이니셜라이저 리스트) 자료형 변수명 = 값;반환자료형 함수명(매개변수자료형 매개변수명){...return 반환값;}자료형* 변수명 = 메모리주소값;자료형* 변수명 = &변수명;int Sum(int A, int B){ 부터 지역 스코프 적용됨#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Add(int a, int b);
int main(void)
{
int c;
int d;
int Print;
scanf("%d", &c);
scanf("%d", &d);
Print = Add(c, d);
printf("%d ", Print);
return 0;
}
int Add(int a, int b) //int c, d에서 전달받음
{
int Sum = a + b;
printf("%d ", Sum);
return Sum; //return a+b도 가능
}
return 0; 으로 main 종료.int add(int a, int b){} 함수를 맨 위에다 int add(int a, int b); 식으로 선언만 해둔다.const: 변경 불가능객체지향 으로 코드 구현하기 용이하게 만든 게 C++.
업데이트, 유지보수 쉽게. 재사용 용이하게 만드는 "객체지향 프로그래밍" 용 Class 문법들
int kor[3]; int eng[3] 같은 게 main에 노출되어서 선언되어 있음. 다른 데서 수정될 가능성 다분class 사용class Student
{
//동작 정의(이를 멤버함수라고 합니다)
double getAvg();
int getMaxNum();
//데이터 정의(이를 멤버변수라고 합니다.)
int kor[3];
int eng[3];
int math[3];
};
#include <iostream>
#include <algorithm> //max 함수 사용
#include <string>
using namespace std;
class Student
{
//동작 정의(이를 멤버함수라고 합니다)
double getAvg(); // 여기서 "이거 멤버함수로 쓴다~" 라고 말해주는 격
int getMaxNum();
//데이터 정의(이를 멤버변수라고 합니다.)
int kor;
int eng;
int math;
};
double Student::getAvg() // 여기서 실제로 함수를 정의하기
{
return (kor + eng + math) / 3.0;
}
int Student::getMaxNum()
{
return max(max(kor, eng), math);
// 다른 방법 return max({ kor, eng, math });
}
접근 연산자 . 사용해서 멤버 함수/변수에 접근. C++ 접근 지정자 public, private, protected 사용 가능.
class 키워드 사용 시, 명시하지 않으면 디폴트는 private. 클래스 외부에서 직접 접근할 경우 컴파일 에러
public은 클래스 외부에서 접근 연산자(.) 로 접근 가능. Likeint main()
{
Student s; //student 클래스의 변수(객체) s 선언 -> "인스턴스화" 라고도 부름
s.getAvg();//s 에서 getAvg() 멤버 함수 접근. public으로 미리 선언되어 있음
return 0;
}클래스 내부에서 private, public 변수, 함수 선언법
private:
//데이터 정의(이를 멤버변수라고 합니다.)
int kor;
int eng;
int math;
int main()
{
Student s;
s.setEngScore(32); //Student의 멤버함수 setEngScore
s.setKorScore(52);
s.setMathScore(74);
//평균 최대점수 출력
cout << s.getAvg() << endl;
cout << s.getMaxScore() << endl;
return 0;
}
class는 설계도에 가까움. 딴 곳에서 선언될 때 하나의 인스턴스(객체)가 생성됨. 이 때 쓰는 게 생성자 // 기본 생성자
Person() {
name = "Unknown";
age = 0;
}
이게 class "내부에" 존재하고 class 선언될 때 가장 먼저 소환됨.
Person p("Alice", 25); 로 선언하고 클래스 내부에선Person(string n, int a) {
name = n;
age = a;
}
로 존재한다.
Person(string n = "DefaultName", int a = 18) 이렇게 표현해 놓는다.#include"" 하는 방식을 자주 쓴다.헤더:
#ifndef BTRMANAGE_H_
#define BTRMANAGE_H_
class BtrManage
{
public:
BtrManage(int startBattery = 100) // Battery(int initialCharge = 100) : charge(initialCharge) { 객체가 생성되면서 초기화
{
battery = startBattery; //객체가 생성된 후에 초기화. battery가 const int 면 초기화가 안될 수 있다.
}
int ReturnBattery();
void UseBattery();
void ChargeBattery();
private:
int battery;
};
#endif
소스코드:
#include <iostream>
#include "BtrManage.h"
using namespace std;
int BtrManage::ReturnBattery()
{
return battery;
}
void BtrManage::UseBattery()
{
if (battery > 5)
{
battery -= 5;
cout << "Used battery! Currently: " << battery << endl;
}
else if(battery>0)
{
battery = 0;
cout << "Used remaining battery. Battery depleted!" << endl;
}
else
{
battery = 0;
cout << "Cannot use battery. Already Depleted." << endl;
}
return;
}
void BtrManage::ChargeBattery()
{
if (battery < 93)
{
battery += 7;
cout << "Charged battery! Currently: " << battery << endl;
}
else if (battery < 100)
{
battery = 100;
cout << "Charged to Full!!" << endl;
}
else
{
battery = 100;
cout << "Cannot charge battery. Already Full." << endl;
}
return;
}
메인:
using namespace std;
int main()
{
BtrManage btr;
BtrManage btr1(15);
cout << btr.ReturnBattery() << endl;
btr.UseBattery();
btr.ChargeBattery();
cout << btr.ReturnBattery() << endl;
cout << btr1.ReturnBattery() << endl;
btr1.UseBattery();
btr1.ChargeBattery();
cout << btr1.ReturnBattery() << endl;
return 0;
}
Battery(int initialCharge = 100) : charge(initialCharge) 로 쓰는 게 낫다. 이건 "새 객체 생성하면서 초기화" 라 const 값도 지정해 줄 수 있음.cout 는 using namespace std; 를 썼으면 문제가 없긴 하지만 std::cout 을 써 버릇 하는 게 좋다 -> 나중에 using namespace std 까먹어서 멘탈붕괴하는 상황이 "무조건" 온다.두 분수의 곱셈을 하는 클래스를 만들어 봅시다
분자는 numerator, 분모는 denominator
두 분수의 곱의 결과는 기약분수로 출력
구현할 메서드
실제 함수 구현만 붙여넣자면:
#include "Fraction.h"
#include <iostream>
int Fraction::setGcd(int a, int b)
{
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
void Fraction::Display()
{
std::cout << "Numerator is: " << numerator << " and denominator is: " << denominator << "\nIn full: " << numerator << "/" << denominator << std::endl;
return;
}
void Fraction::Simplify()
{
int gcd = 1; //혹시몰라서 1로
gcd = setGcd(numerator, denominator);
numerator = numerator / gcd;
denominator = denominator / gcd;
std::cout << "Simplified to: " << numerator << "/" << denominator << std::endl;
return;
}
Fraction Fraction::Multiply(Fraction other) //const Fraction& other 로 받으면 더 깔끔하다. 레퍼런스만 받기+수정 불가능
{
int newNumerator;
int newDenominator;
newNumerator = numerator * other.numerator;
newDenominator = denominator * other.denominator;
Fraction f3(newNumerator, newDenominator);
f3.Simplify();
std::cout << "Multiplication complete!" << std:: endl;
return f3;
}
포인트:
Fraction Fraction::Multiply(const Fraction& Other) 형식으로 받아오는 Fraction 클래스의 경우 &으로 레퍼런스로, const로 수정불가능하게 가져오는 게 안전{
Fraction Result(numerator*other.numerator, denominator*other.denominator);
Result.Simplify();
return Result;
}
이렇게도 가능
f3 = f1.Multiply(f2); 이런 방식으로도 만들 수 있다.class 는 C언어의 struct 를 확장해서 객체지향적 개념 추가한 것protected 멤버 변수: private 와 달리 상속받은 클래스에선 접근 가능i. e.) 자동차: 공통적으로 가지는 속성 속도/색상 이 있다 치자.
이런 공통특성을 모든 차량에 개별적으로 개별 구현하는 대신, 하나의 기본 클래스를 정의하고 이를 활용해서 유지보수를 용이하게 한다.
멤버 초기화: 아까 위에서 한 Battery(int initialCharge = 100) : charge(initialCharge) 같이 생성자 코드보다 먼저 멤버 변수를 초기화(값 설정) 해줄 수 있는 방법.
자식 클래스의 생성자는 부모 클래스의 생성자를 호출 가능
Bicycle(string c, int s, bool basket) : Vehicle(c, s), hasBasket(basket) {}color와 speed에 고유한 값을 가지는 Vehicle을 호출하고 그 값을 가져와서 속도와 색상이 지정된 클래스가 될 수 있다.virtual 을 앞에 붙여주면 virtual int func()int func() 를 각자 "구현" 할 수 있게 됨.void print(Animal* animal)
{
animal->bark();
}
Is A 테스트 도입해 보기virtual int func() 뒤에 =0; 만 붙여주면 바로 순수가상함수-> 연산자: 클래스에서 멤버 접근할 땐 mydog.makesound() 같이 . 써줬다myAnimal = &myDog) 해당 주소 클래스의 멤버에 접근할 땐 myAnimal->makeSound();