C++ function, class

이영준·2022년 3월 26일
0
post-thumbnail

🔑함수

• 함수는 작업을 수행한 후 제어권을 호출자에게 반환하는 코드 블록입니다.
• C 및 C++ 프로그래밍에서는 모든 실행 가능한 코드가 함수 내에 존재합니다.
• 함수는 종종 프로그램을 한 번 실행하는 동안 여러 곳에서 여러 번 실행(호출)됩니다.
• 서브루틴을 종료하면 프로그램은 콜 후 포인트로 분기(복귀)합니다.
• 함수의 연산은 매개 변수를 사용하여 변경할 수 있습니다.
• 함수 선언의 인수는 함수 호출로 전달된 매개변수에 명확하게 대응합니다.
• 함수에 리턴 타입이 있는 경우 콜은 반환값을 가진 것으로 평가되어 변수로 저장 가능.

#include <iostream>
using namespace std;

float calculateCircle(int radius) {
	return 3.14 * radius * radius;
}

int main() {
	int min, max, radius;
	cout << "Enter Min (1~10) : " ;
	cin >> min;
	cout << "Enter Max (Min~10) : " ;
	cin >> max;

	for (int i = min; i < max + 1; i++) {
		cout << "Radius " << i << "=3.14x" << i << "x" << i << "=" << calculateCircle(i) << "\n";
	}

		
}

결과:
Enter Min (1~10) : 2
Enter Max (Min~10) : 10
Radius 2=3.14x2x2=12.56
Radius 3=3.14x3x3=28.26
Radius 4=3.14x4x4=50.24
Radius 5=3.14x5x5=78.5
Radius 6=3.14x6x6=113.04
Radius 7=3.14x7x7=153.86
Radius 8=3.14x8x8=200.96
Radius 9=3.14x9x9=254.34
Radius 10=3.14x10x10=314

Inline Function

• 인라인 함수가 'inline' 키워드를 사용하여 정의되면 함수가 호출될 때마다 컴파일러는 함수 호출을 함수의 실제 코드로 바꿉니다.
• 인라인 함수는 function-calling-overhead가 저장되기 때문에 일반 함수보다 조금 빠르게 실행되지만 메모리 패널티가 발생합니다.
– 인라인 함수를 10회 호출하면 함수의 복사본이 코드에 10개 삽입됩니다.
• 인라인 함수는 자주 호출되는 작은 함수에 적합합니다.

변수로 따로 선언하지 않고 바로 함수의 반환값을 사용할 수 있는 함수로 보인다.

#include <iostream>

using namespace std;

inline int inc(int x) {
	return x + 1;
}
int main() {
	cout << inc(1) << endl;
}

Recursive Functions 재귀 함수

재귀 함수는 자신을 호출하거나 함수 호출의 잠재적 사이클에 있는 함수입니다.

factorial

#include <iostream>

using namespace std;

int Factorial(int n) {
	if (n == 1)
		return 1;
	return Factorial(n - 1) * n;
}

int main() {
	int result = Factorial(4);
	cout << "Factorial :" << result << "\n";

	return 0;
}

fibonacci

#include <iostream>

using namespace std;

int Fibo(int n) {
	if (n == 1)
		return 1;
	if (n == 2)
		return 1;
	return Fibo(n - 1) + Fibo(n-2);
}

int main() {
	int result = Fibo(8);
	cout << "Fibo :" << result << "\n";

	return 0;
}

🔑클래스

• 클래스는 데이터 및 함수(메서드라고도 함)를 멤버로 하는 키워드 클래스를 사용하여 선언된 사용자 정의 유형 또는 데이터 구조입니다.
• 클래스는 데이터 구조의 확장된 개념입니다. 데이터 구조처럼 데이터 구성원을 포함할 수 있지만 구성원으로서의 기능도 포함할 수 있습니다.

인스턴스(객체)

• 인스턴스는 클래스의 구체적인 선언입니다.
• 정식 "instance"는 "object"와 동의어입니다.
• 인스턴스마다 독자적인 데이터가 있습니다.
• 생성된 인스턴스의 생성을 인스턴스화라고 합니다.

접근 지정자(private, public, protected)

지정자접근성
privateAccessible only within the same class (not from outside the class)
따로 private:으로 쓰지 않아줘도 기본적으로 클래스 내의 변수들은 private으로 저장되는 듯 함
publicAccessible within the class as well as from outside the class.
protectedThe members declared as "protected" cannot be accessed from outside the class, but can be accessed from a derived class.
This is used when inheritance is applied to the members of a class.
클래스 외부에서 액세스할 수 없지만 파생 클래스에서 액세스할 수 있습니다. 이는 상속이 클래스 멤버에 적용될 때 사용됩니다.

선언과 정의

클래스의 경우 선언을 클래스 내에서, 그 메서드의 정의를 클래스 밖에서 할 수 있다

ex) Calculate Area 메서드를 클래스 밖에서 정의했다.

#include <iostream>
using namespace std;

class Quadrangle {
private:
	int width;
	int height;
	int area;

public:
	int CalculateArea(int argWidth, int argHeight);
	void SetWidth(int width){
		Quadrangle::width = width;
	}
	void SetHeight(int height) {
		Quadrangle::height = height;
	}

};

int Quadrangle::CalculateArea(int argWidth, int argHeight) {
	width = argWidth;
	height = argHeight;
	area = width * height;
	return area;
}

void main() {
	int w, h;
	Quadrangle cQ;

	cout << "Enter Width : ";
	cin >> w;
	cout << "Enter Height : ";
	cin >> h;

	cQ.SetHeight(h);
	cQ.SetWidth(w);
	cout << "Area (w = " << w << ", h=" << h << ") =" << cQ.CalculateArea(h, w);

}

클래스 선언 퀴즈

#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;

class Circle {
private:
	int radius;

public:
	void SetRadius(int radius_) {
		radius = radius_;
	}

	float CalculateArea() {
		return radius * radius * 3.14;
	}
};



int main() {
	int radius = 0;
	Circle circle;

	printf("Input radius: (cm)\n");
	scanf_s("%d", &radius);

	circle.SetRadius(radius);
	printf("Area (radius=%d) = %0.3f\n", radius, circle.CalculateArea());
}

결과:
Input radius: (cm)
3
Area (radius=3) = 28.260

생성자와 소멸자 (Constructor and Destructor)

생성자
• 클래스의 인스턴스가 생성될 때마다 생성자가 호출됩니다.
• 생성자의 이름은 클래스와 같으며 형식을 반환하지 않습니다.
• 클래스에 생성자가 없어도 컴파일러는 암묵적인 디폴트 생성자라고 불리는 생성자에 대한 코드를 생성합니다.

소멸자
• 클래스의 객체가 소멸될 때마다 소멸자가 호출됩니다.
• 소멸자의 이름은 같은 방식으로 정의되지만 앞에 '~'가 있습니다.
• 클래스에 소멸자가 없어도 컴파일러는 디폴트 소멸자라고 불리는 소멸자에 대한 코드를 생성합니다.

#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;

class Unit {
	int status;
public:
	Unit(int a);
	~Unit();
	void fly();
};

Unit::Unit(int a) : status(a) {};
Unit::~Unit() {
	cout << "Unit Destructing";
	status = 0;
}

void Unit::fly() {
	cout << status << endl;
}

int main() {
	Unit oUnit(1);
	oUnit.fly();
	return 0;
}

참고로 위의 생성자나 소멸자의 정의에서`

Unit::Unit(int a) {
	status = a;
}

와 같은 소멸자 정의를

 Unit::Unit(int a) : status(a) {};

와 같은 형태로 바꿀 수 있음

생성자 소멸자 퀴즈

#include <iostream>

using namespace std;

class Student {
	int Year;
	int ID;
	int Grade;

public:
	Student(int Year, int iD, int grade) : Year(Year), ID(iD), Grade(grade) {}
	void showData() {
		cout << "Year : " << Year << ", ID: " << ID << ", Grade : " << Grade;
	}
};

int main() {
	Student s(2017, 100100, 1);
	s.showData();
}

결과:Year : 2017, ID: 100100, Grade : 1

보다 더 직관적인 코드는

#include <iostream>

using namespace std;

class Student {
	int Year;
	int ID;
	int Grade;

public:
	Student(int Year, int iD, int grade)  {
	    Student::Year = Year;
	    ID = iD;
	    Student::Grade = grade;
	}
	void showData() {
		cout << "Year : " << Year << ", ID: " << ID << ", Grade : " << Grade;
	}
};

int main() {
	Student s(2017, 100100, 1);
	s.showData();
}

위와 같을 것이다.

상속

• 상속을 통해 다른 클래스의 관점에서 클래스를 정의할 수 있으므로 응용 프로그램을 쉽게 만들고 유지할 수 있습니다.
• 코드 재사용 및 원래 소프트웨어의 독립적 확장을 허용하는 메커니즘입니다.

#include <iostream>
using namespace std;

class NPC {
	int defense;

public:
	void SetDefense(int n);
	int GetDefense();
};

class Grunt : public NPC {
	int armor;

public:
	void SetArmor(int n);
	int GetArmoredDefense();
};

void NPC::SetDefense(int n) {
	defense = n;
}

int NPC::GetDefense() {
	return defense;
}

void Grunt::SetArmor(int n) {

	armor = n;
}

int Grunt::GetArmoredDefense() {
	return armor + GetDefense();
}

int main() {
	Grunt oUnit;
	oUnit.SetDefense(10);
	oUnit.SetArmor(20);

	cout << "Get Armored Defense : " << oUnit.GetArmoredDefense() << "\n";
	return 0;
}
Grunt 클래스에서 NPC 클래스의 public 요소들을 가져와 사용하여 메서드를 통해 defense값을 줄 수 있다.

상속 퀴즈

#include <iostream>

using namespace std;
class P {
public:
	int x=10;
protected:
	int y=10;
private:
	int z=10;
};

class A : public P {

};

class B : protected P{

};

class C : private P{

};

int main() {
	A a;
	B b;
	C c;
	cout << a.x << endl;
	cout << a.y << endl;
	cout << a.z << endl;
	cout << b.x << endl;
	cout << b.y << endl;
	cout << b.z << endl;
	cout << c.x << endl;
	cout << c.y << endl;
	cout << c.z << endl;
	
}

결과:
a.x출력을 제외하면 모두 오류가 발생

이유
public으로 P를 상속 받은 a는 접근제한자가 public 이상인 x를 public변수로 그대로 받아오고, 나머지 접근 제한자는 그대로 받아짐
b는 protected보다 접근 제한 범위가 큰 x를 protected로 받아오기 때문에 모든 변수가 public이 아니므로 접근 불가
c 역시 private보다 넓은 범위인 요소들을 모두 private으로 바꿔서 상속받음

다중 상속

클래스는 여러 부모 클래스에서 변수 및 메서드를 상속할 수 있습니다. 클래스가 특정 클래스에서 상속될 수 있는 단일 상속과는 다릅니다.

다중 상속 퀴즈

#include <iostream>
//re: 실수
//im: 허수

using namespace std;

class Plus {
public:
	void printPlus(int re1, int im1, int re2, int im2) {
		cout << "Plus: " << re1 + re2 << "+" << im1 + im2 << "j" << endl;
	};
};

class Minus {
public:
	void printMinus(int re1, int im1, int re2, int im2) {
		cout << "Minus: " << -re1 + re2 << "+" << -im1 + im2 << "j" << endl;
	};
};

class Complex : public Plus, public Minus {
private:
	int re;
	int im;

public:
	Complex() : re(0), im(0) {};

	void setCom(int are, int aim) {
		re = 0;
		im = 0;
		re += are;
		im += aim;
	}

	void plus(int are, int aim) {
		printPlus(are, aim, re, im);
	}

	void minus(int are, int aim) {
		printMinus(are, aim, re, im);
	}
};
void main() {
	Complex a;

	a.plus(2, 3);
	a.minus(2, 3);

	a.setCom(1, 1);
	a.plus(2, 3);
	a.minus(2, 3);
}

클래스 포인터

• 클래스에 대한 포인터는 구조체에 대한 포인터와 정확히 동일한 방식으로 작동됩니다.
• 멤버 액세스 연산자 '->'를 사용할 수 있습니다

ex)

Grunt *pUnit = new Grunt;

pUnit -> SetDefence(10);
pUnit -> SetArmor(20);

delete pUnit;

or

Grunt oUnit;
Grunt *pUnit;
pUnit = &oUnit;
pUnit->SetDefense(10);
pUnit->SetArmor(20);

클래스 포인터 퀴즈

void main() {
	Complex *a = new Complex;

	a->plus(2, 3);
	a->minus(2, 3);

	a->setCom(1, 1);
	a->plus(2, 3);
	a->minus(2, 3);
	
	delete a;
}

생성자 상속

• 생성자는 상속되지 않습니다.
• 상위 클래스의 생성자는 하위 생성자가 암시적으로 또는 명시적으로 호출해야 합니다.
• 상위 클래스의 생성자가 먼저 호출되고 하위 클래스의 생성자가 나중에 호출됩니다.

상속받은 자식 클래스를 호출하면 부모 클래스의 생성자를 먼저 호출하고 자신의 생성자를 호출한다.
Derived::Derived(int a) : Base(a)에서 명시적으로 생성자를 불러줘 부모클래스의 매개변수가 있는 생성자를 호출할 수 있다.

#include <iostream>
using namespace std;

class Base {
public:
	Base();
	Base(int a);
	~Base();
};

Base::Base() {
	cout << " Constructor of Base " << endl;
} 

Base::Base(int a) {
	cout << "Constructor of Base " << a << endl;
}

Base::~Base() {
	cout << " Destructor of Base " << endl;
} 

class Derived : public Base {
public: 
	Derived();
	Derived(int a);
	~Derived();
};

Derived::Derived() {
	cout << " Constructor of Derived " << endl;
}

Derived::Derived(int a){
	cout << " Constructor of Derived " << a << endl;
}

Derived::~Derived() {
	cout << " Destructor of Derived " << endl;
}

void main() {
	Derived obj1;
	Derived obj2(1);
}

생성자 상속 퀴즈

#include <iostream>
using namespace std;

class Student {
public:
	Student() : grade(0) {}
	Student(int argGrade) : grade(argGrade) {}
	~Student(){}
	int GetGrade() { return grade; }

private:
	int grade;
};

class Calculator {
public:
	Calculator() : numberOfStudent(0) {}
	void AddStudent(Student argStudent);
	int Sum();

private:
	Student student[50];

protected:
	int numberOfStudent;
};

void Calculator::AddStudent(Student argStudent) {
	//student 객체 추가하기
	student[numberOfStudent++] = argStudent;
}

int Calculator::Sum() {
	int sum = 0;
	for (int i = 0; i < numberOfStudent; i++)
		sum +=student[i].GetGrade();
	return sum;
}

class CalculatorEx :public Calculator {
public:
	int Average() {
		float average(0.0f);
		average = Sum() / float(numberOfStudent);
		return average;
	}
};

int main() {
	Student student1(30);
	Student student2(90);
	Student student3(100);
	Student student4(50);

	CalculatorEx cal;
	cal.AddStudent(student1);
	cal.AddStudent(student2);
	cal.AddStudent(student3);
	cal.AddStudent(student4);
	
	cout << "Sum of grades : " << cal.Sum() << endl;
	cout << "Average of grades : " << cal.Average() << endl;

}
profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글