https://www.nextree.co.kr/p6960/
2번 + 4번 + 5번 -> 프레임웍
#include <iostream>
using namespace std;
class Cat {
public:
void cat_speak() {
cout << "야옹~~" <<endl;
}
};
class Dog {
public:
void dog_speak() {
cout << "멍멍~~" <<endl;
}
};
class Cow { // 추가함
public:
void cow_speak() {
cout << "음머~~" <<endl;
}
};
class Zoo {
private:
Cat cat;
Dog dog;
Cow cow; //추가함
public:
void speak(){
cat.cat_speak();
dog.dog_speak();
cow.cow_speak(); //추가함
}
};
int main(){
Zoo zoo;
zoo.speak();
}
int main(int argc, char** argv){
int a = 10;
int b = 20;
int sum;
// 컴파일 타임 : 컨파일 하는 시간
// 런타임 : 실행되면서 걸리는 시간
sum = 10 + 20; // 정적인 코드 : 컨파일 타임
sum = a + b; // 정적인 코드
// 속성 - 디버깅 - 명령인수 - '10, 20' 필요함
// argv[0] : 파일명
int a2 = atoi(argv[1]);
int b2 = atoi(argv[2]);
sum = a2 + b2; // 런타임 코드 계산
cout << a2 << " + " << b2 << " = " << sum << endl;
}
// cmd에서 입력 방법
// [파일명].exe 10 20
컴파일러가 실수하는 것을 알려줌
int add(const int a, const int b){
return a+b;
}
int main() {
int a = 10;
int b = 20;
int sum;
sum = add(a, b); // 런타임 코드 계산
// debug mode -> 함수로 정상 동작함 : runtime 시 계산함
// release mode -> 최적화로 정적코드로 동작함 (sum = 30)
}
release mode
debug mode
생성(exe 만들기) : 일반적인 경우 debug모드가 exe 생성시 좀더 빠르다
실행 : 일반적으로 release 모드의 결과물이 빠르다
크기 : debug 모드가 크다. release 모드가 보통 debug 모드 대비 1/4 정도 작다.
도구 - 옵션 - 프로젝트 및 솔루션 - vc++ 프로젝트 설정 - 빌드 타이밍 - 예
->> 다시 빌드 진행
- 빌드 : 수정된 소스만 다시 빌드
- 다시 빌드 : 처음부터 다시 진행
일반화 : sum = a + b;
특별화 : sum = 10 + 20;
int main() {
int a = 10;
int b = 20;
int c = 10;
int d = 20;
sum = a + b; // 변수명에 대해서 특별화
sum = c + d; // 변수명에 대해서 특별화
p1 = &a;
p2 = &b;
sum = *p1 + *p2;
p1 = &c;
p2 = &d;
sum = *p1 + *p2;
// 일반화 : 외형적으로 같지만, 실행되는 내용이 다름
// 일반화는 대부분 포인터로 사용할 수 밖에 없음
}
포인터 사용 이유
// typedef oldType newType;
typedef unsigned int UINT;
// typedef type 변수명 : type을 새로운 변수명으로 정의
// int (*)(const int, const int); // 함수 포인터
typedef int (*FP_CALC)(const int, const int); // 함수 포인터 재정의
FP_CALC calc; // calc : 포인트 변수명
// c style
int add(const int a, const int b){
return a+b;
}
int sub(const int a, const int b){
return a-b;
}
class Calc{
public:
virtual int calc(const int a, const int b) = 0;
};
class AddCalc : public Calc {
public:
virtual int calc(const int a, const int b) override {
return a + b;
}
};
class SubCalc : public Calc {
public:
virtual int calc(const int a, const int b) override {
return a - b;
}
};
class MulCalc : public Calc {
public:
virtual int calc(const int a, const int b) override {
return a * b;
}
};
// c style
int MyCalc(Calc& obj, const int a, const int b){
// 변경되는 것 없음. 새로운 기능 자연스럽게 실행할 수 있음 >> OCP
return obj.calc(a, b);
}
int main() {
// c style
result = add(a, b); // add 함수 : 컴파일 때 결정되는 함수
result = sub(a, b);
// 함수명에 대해서 특별화
calc = add;
result = calc(a, b); // 실행 중에 결졍(그 윗줄에서 정의되는 함수에 따라 달라짐)
calc = sub;
result = calc(a, b);
// cpp style
Calc* pCalc = new AddCalc();
result = pCalc->calc(a, b); // a+b
delete pCalc;
pCalc = new SubCalc();
result = pCalc->calc(a, b); // a-b
delete pCalc;
AddCalc addCalc;
Calc& objA = addCalc;
result objA.calc(a, b);
SubCalc subCalc;
Calc& objB = subCalc;
result objB.calc(a, b);
// c style
result = MyCalc(addCalc, a, b); // MyCalc가 고정했을 때 일반화
result = MyCalc(subCalc, a, b);
// 새롭게 추가된 부분
MulCalc mulCalc;
result = MyCalc(mulCalc, a, b);
// 기존의 코드를 변경하지 않음
vector<Calc*> arr = {&addCalc, &subCalc, &mulCalc};
// 전달해주는 순서에 따라 달라짐
/*for(int i = 0;i<arr.size();i++) { // 옛날 방식
MyCalc(*arr[i], a, b); // 런타임에 의해 결정
}*/
for(auto& pCalc : arr) { // 요즘 방식
MyCalc(*pCalc, a, b);
}
}
함수 포인터 재정의 후 사용
OCP에 대하여 설명!!! 확인해보기!!
기존 그림 : Direct
확장성 고려된 그림 : Indirect
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() const = 0;
// const 안써주면 구문오류 발생! >> 테스팅 해보기
};
class Cat : public Animal {
public:
virtual void speak() const override {
// virtual 과 override 도 약속처럼 써주기
cout << "야옹~~" <<endl;
}
};
class Dog : public Animal {
public:
virtual void speak() const override {
cout << "멍멍~~" <<endl;
}
};
class Cow : public Animal { // 추가함
public:
virtual void speak() const override {
cout << "음머~~" <<endl;
}
};
class Zoo {
private:
vector<Animal*> array; // 추가하는 함수 필요
public:
void addAnimal(const Animal* const pAnimal) {
// pAnimal++; // 구문 오류를 위해 인자를 const로 선언
// 포인터 변수를 이용해서 포인터를 변경하면 컴파일 오류를 발생하게 설정
array.push_back(pAnimal);
}
void speak(){
for(const auto& pAnimal : array) {
// 읽기 전용이므로 const로 선언
pAnimal->speak();
}
}
};
int main(){
Zoo zoo;
Cat cat;
Dog dog;
Cow cow;
zoo.addAnimal(&cat);
zoo.addAnimal(&dog);
zoo.addAnimal(&cow); // 추가함
// 기존 내용 변경 없이 추가 가능
zoo.speak();
return 0;
}
BOOL InitInstance(Zoo* pZoo) {
Zoo zoo;
Cat cat;
Dog dog;
Cow cow;
zoo.addAnimal(&cat);
zoo.addAnimal(&dog);
zoo.addAnimal(&cow);
return TRUE;
}
BOOL Run(Zoo* pZoo) {
pzoo->speak();
return TRUE;
}
BOOL ExitInstance(Zoo* pZoo) {
return TRUE;
}
int main(){
Zoo zoo;
InitInstance(&zoo);
// InitInstance 내부만 수정하면 프로그램 변경 가능
Run(&zoo);
ExitInstance(&zoo);
return 0;
}
// 프레임웍 : 사전에 약속된 내용을 지키면서 프로그램 수정 진행
MFC는 위와 같이 하나의 function만 수정하면 가능
기존 c/c++ 처럼 main()을 수정해야 하는 것이 아님