Home C EXAMPLES: CLASS
Post
Cancel

C EXAMPLES: CLASS

필자의 대학 코스 Advanced Programming에서 사용된 예시를 발췌, 정리했습니다. FINAL 시험에서 좋은 성과를 바라며…

Rectangle Class

rectangle.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef RECTANGLE_H
#define RECTANGLE_H

#include <iostream>

class rectangle {
	double width, height; // 멤버 변수
public:
	rectangle(double w, double h) : width(w), height(h) {} // 생성자
	double get_width() const { return this->width; } // 멤버 함수
	double get_height() const { return this->height; } // 멤버 함수
};

std::ostream &operator<<(std::ostream &, rectangle const &);

#endif

rectangle.cpp

1
2
3
4
5
6
7
8
#include "rectangle.h"

using namespace std;

ostream &operator<<(ostream &out, rectangle const &r) {
	return out << "rectangle (width:" << r.get_width() << ",height:" << r.get_height() << ")";
}

main.cpp

1
2
3
4
5
6
7
8
9
#include "rectangle.h"
#include <iostream>

int main() {
	using namespace std;
	rectangle r(10, 5);
	cout << r << endl;
	return 0;
}

출력

1
rectangle (width:10, height:5)

Bank Account Class

bank-account.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef BANK_ACCOUNT_H
#define BANK_ACCOUNT_H

class bank_account
{
	unsigned long balance;
public:
	bank_account(unsigned long b=0) : balance(b) {}
    bank_account& operator+=(unsigned long);
    unsigned long get_balance() const { return this->balance; }
    bool transfer_to(bank_account &, unsigned long );
};

#include <iostream>
std::ostream& operator<<(std::ostream &, bank_account const &);

#endif

bank-account.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "bank-account.h"

bank_account& bank_account::operator+=(unsigned long amt)
{
    this->balance += amt;
    return *this;
}

bool bank_account::transfer_to(bank_account &other, unsigned long amt)
{
    if (this->balance >= amt)
    {
        this->balance -= amt; // 여기는 되는 이유: 멤버 함수니까!
        other.balance += amt;
        return true;
    }
    else
    {
        return false;
    }
    
}

using namespace std;
ostream& operator<<(ostream& out, bank_account const &accct)
{
    return out << "Balance: " << acct.get_balance(); // 여기를 balance로 하면 안되는 이유: balances는 private 멤버 변수
}

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "bank-account.h"
#include <iostream>

using namespace std;

int main()
{
    bank_account a;
    bank_account b = 50;
    a += 100;
    b += 1000;
    if (!a.transfer_to(b, 1))
        cerr << "could not transfer money" << endl;
    cout << a << endl << b << endl;
    return 0; 
}

출력

1
2
Balance: 99
Balance: 1051

Fraction Class

fraction.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef FRACTION_H
#define FRACTION_H

#include <iostream>

class fraction
{
	int num;
    unsigned denom;
public:
	fraction(int num, unsigned denom=1) : num(num), denom(denom) {} // initializer list
    fraction(fraction const &f) : num(f.num), denom(f.denom) {}
    fraction& operator*=(fraction const &);
    fraction operator*(fraction const &) const; // 관습적으로 쪼개서 구현한다! / 뒤에 붙는 const는, 값을 읽어서 반환만 하므로 (수정하지 않으므로) const가 붙는다
    fraction& operator+=(fraction const &);
    fraction operator+(fraction const &) const; 
    fraction& operator-=(fraction cons &) { return *this += -other; }
    fraction operator-(fraction const &) const {return *this + -other; }
    fraction operator-() const { return fraction(-num, denom); }
    friend std::ostream& operator<<(std::ostream &, fraction const &); // 요친구는 fraction의 친구, 즉 fraction의 멤버 변수에 접근 가능
};

#endif

fraction.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "fraction.h"

fraction& fraction::operator*=(fraction const &other)
{
    this->num *= other.num;
    this->denom *= other.denom;
    return *this;
}

fraction fraction::operator*(fraction const &other) const
{
    fraction f = *this; // 복사 생성자 필요!
    return f *= other; // 최대한 위에 쓴 걸 활용하자
}

fraction& fraction::operator+=(fraction const &other) {
	unsigned new_denom = this->denom * other.denom;
	this->num = this->num * other.denom + this->denom * other.num;
	this->denom = new_denom;
	return *this;
}

fraction fraction::operator+(fraction const &other) const {
	fraction f = *this;
	return f += other;
}

using namespace std;
ostream& operator<<(ostream& out, fraction const &f)
{
    return out << f.num << "/" << f.denom;
}

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "fraction.h"
#include <iostream>

using namespace std;

int main()
{
    fraction f = -2;
    fraction g(5, 7);
    cout << f << endl << g << endl;
    cout << f * g << endl;
    cout << f * g - 1 << endl;
    return 0; 
}

출력

1
2
3
4
-2/1
5/7
-10/7
-17/10

Set Class

set.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef SET_H
#define SET_H

#include <cstddef> // for size_t

class integer_set
{
	int* elements;
    size_t num_elements;
public:
	integer_set();
	~integer_set() { delete [] this->elements; }
	integer_set& operator+=(int);	// insert an int into the set
	integer_set& operator-=(int);	// remove an int from the set
	bool operator[](int) const; // 있는지 없는지 체크
};

#endif

set.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "set.h"

integer_set::integer_set() : elements(new int[0]), num_elements(0) {}

integer_set::integer_set(integer_set const &other)
		: elements(new int[other.num_elements]), num_elements(other.num_elements) {
	for (size_t i = 0; i < this->num_elements; i++)
		this->elements[i] = other.elements[i];
}

integer_set& integer_set::operator=(integer_set const &other) {
	if (this->num_elements < other.num_elements) {
		delete [] this->elements;
		this->elements = new int[other.num_elements];
	}
	this->num_elements = other.num_elements;
	for (size_t i = 0; i < this->num_elements; i++)
		this->elements[i] = other.elements[i];
	return *this;
}

integer_set& integer_set::operator+=(int val) {
	if ((*this)[val])	return *this;
	int* bigger = new int[this->num_elements + 1];
	for (size_t i = 0; i < this->num_elements; i++)
		bigger[i] = this->elements[i];
	bigger[this->num_elements] = val;
	delete [] this->elements;
	this->elements = bigger;
	this->num_elements++;
	return *this;
}

integer_set& integer_set::operator-=(int val) {
	if (!(*this)[val])	return *this;
	int* val_location = this->elements;
	for (size_t i = 0; i < this->num_elements; i++)
		if (this->elements[i] == val)
			val_location = &this->elements[i];
	*val_location = this->elements[this->num_elements - 1];
	this->num_elements--;
	return *this;
}

bool integer_set::operator[](int val) const {
	for (size_t i = 0; i < this->num_elements; i++)
		if (this->elements[i] == val)
			return true;
	return false;
}

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "set.h"
#include <iostream>

int main() {
	using namespace std;
	integer_set s;
	s += 1;
	cout << "0 is in the set? " << s[0] << endl;
	cout << "1 is in the set? " << s[1] << endl;

	integer_set t = s;
	t += 3;
	cout << "3 is in the set? " << t[3] << endl;

	s = t;
	s += 2;
	cout << "2 is in the set? " << s[2] << endl;

	return 0;
}

출력

1
...

가변 길이 TEMPLATE을 이용한 SUM FUNCTION

가변 길이 템플릿의 구 버전

1
2
3
4
5
6
7
#define SUM_FUNCTION(tp)    tp sum_ ## tp(tp const* arr, size_t n) { \
                                tp total = 0; \
                                for (size_t i = 0; i < n; i++) \
                                    total += arr[i];
                                return total;
                            }
SUM_FUNCTION(int)

sum.h

1
2
3
4
5
6
7
8
#ifndef SUM_H
#define SUM_H

#include <cstddef>

template <typename T> T  sum(T const *, size_t);

#include 

sum.cc

1
2
3
4
5
6
7
8
9
10
#include "sum.h"

template <typename T> T sum(T const *xs, size_t n)
{
    T total = 0;
    for (size_t i = 0; i < n; i++) total += xs[i];
    return total;
}

template int sum<int> (int const *, size_t);

main.cc

1
2
3
4
5
6
7
8
9
10
11
int main() {
	using namespace std;
	int x[] = { 3, 4, 5 };
	cout << sum<int>(x, 3) << endl;
	double y[] = { 9.5, 10, 10.5 };
	cout << sum(y, 3) << endl;

	value<double> a;
	cout << a.get_value() << endl;
	return 0;
}

출력

1
...

TEMPLATE을 이용한 LIST 클래스

list.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef LIST_H
#define LIST_H

#include <cstddef>		// for size_t

template<typename T>
class list {
	T* elements;
	size_t num_elements;
public:
	list() : elements(new T[0]), num_elements(0) {}

	// rule of 3
	~list() { delete [] elements; }
	list(list const &) : elements(new T[other.num_elements]), num_elements(other.num_elements) {
        for (size_t i = 0; i < this->num_elements; i++)
            this->elements[i] = other.elements[i];
    }
	list& operator=(list const &){
        delete [] elements;
        this->num_elements = other.num_elements;
        this->elements = new T[this->num_elements];
        for (size_t i = 0; i < this->num_elements; i++)
            this->elements[i] = other.elements[i];
        return *this;
    }

	size_t length() const { return this->num_elements; }
	T& operator[](size_t index) {
        if (index >= this->num_elements) {
            T* new_elements = new T[index + 1];
            for (size_t i = 0; i < this->num_elements; i++)
                new_elements[i] = this->elements[i];
            delete [] this->elements;
            this->elements = new_elements;
            this->num_elements = index + 1;
        }
        return this->elements[index];
    }
};

/*
 * list<int> l;
 * l[0] = 4;		// adding something new to the list
 * l[0]++;			// modifying something in the list
 * cout << l[0] << endl;		// retrieving from the list
 */

#endif

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include "list.h"

int main()
{
    using namespace std;
    list<int> l;
    l[0] = 4;
    l[0]++;
    l[3] = l[0] * 9;
    for (size_t i = 0; i < l.length(); i++)
        cout << l[i] << " ";
    cout << endl;
    return 0;
}

STL:VECTOR 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>

int main()
{
    using namespace std;
    vector<int> v;
    v.push_back(2);
    v.push_back(3);
    cout << v[0] << " " << v[1] << endl;
    for (int x : v)
        cout << x << endl;
    return 0;
}

INHERITANCE: SHAPE CLASS

shape.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

enum col {black, red, white};

class shape
{
    col colour;
public:
    shape(col c) : colour(c) {}
    virtual double area() const { return 0; }
    virtual double perimeter() const { return 0; }
};

class circle : public shape {
    double radius;
public:
    circle(col c, double r) : shape(c), radius(r) {}
    virtual double area() const
    {
        return 3.14 * this->radius * this->radius;
    }
    virtual double perimeter() const
    {
        return 2 * 3.14 * this->radius;
    }
};

class triangle : public shape {
    double base, height;
public:
    triangle(col c, double b, double h) : shape(c), base(b), height(h) {}
    virtual double area() const { return this->base * this->height / 2; }
};

int main()
{
    using namespace std;
    triangle t(col::red, 3, 4);
    circle c(col::black, 5);
    //shape s = c; // 부모에 자식 대입은 불가능!
    shape& s = c; // 이건 가능
    cout << t.area() << " " << c.area() << endl;
    cout << t.perimeter() << " " << c.perimeter() << endl;
    cout << s.area() << " " << s.perimeter() << endl; // virtual이 있기 때문에 c에 대한 정보로 처리, 없으면 s로 처리
    return 0;
}

NUMBER CLASS

number.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>

using namespace std;

class number {
protected:
	virtual double real_value() const = 0;
	virtual double imaginary_value() const;
public:
	virtual complex_number operator+(number const &other) const {
		double r = this->real_value() + other.real_value();
		double i = this->imaginary_value() + other.imaginary_value();
		return complex_number(r, i);
	}
};

class integer : public number {
	int val;
public:
	integer(int v) : val(v) {}
	virtual double real_value() const { return this->val; }
	virtual double imaginary_value() const { return 0; }
};

class real : public number {
	double val;
public:
	real(double v) : val(v) {}
	virtual double real_value() const { return this->val; }
	virtual double imaginary_value() const { return 0; }
};

class complex_number : public real {
	double imag;
public:
	complex_number(double r, double i) : real(r), imag(i) {}
	virtual double imaginary_value() const { return 0; }
};

LIBRARY CLASS with ptr vector

library.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef LIBRARY_H
#define LIBRARY_H

#include <vector>

class library_item;

class library {
	std::vector<library_item*> catalogue; // library_item is not defined! prototype
public:
	library() : catalogue(std::vector<library_item*>()) {}
	void add_library_item(library_item *);
	int how_many_overdue(int days_after) const;
};

class library_item {
	bool is_checked_out;
public:
	virtual int borrowing_period() const { return 7; }
	library_item() : is_checked_out(false) {}
	virtual void loan() { this->is_checked_out = true; }
	virtual void give_back() { this->is_checked_out = false; }
	virtual bool can_borrow() const { return !this->is_checked_out; }
	virtual bool is_late(int days_after) const {
		return days_after > this->borrowing_period();
	}
};

class book : public library_item {
public:
	book() : library_item() {}
	virtual int borrowing_period() const { return 14; }
};

class journal : public library_item {
public:
	journal() : library_item() {}
};

#endif

library.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "library.h"

using namespace std;

void library::add_library_item(library_item *new_item) {
	this->catalogue.push_back(new_item);
}

int library::how_many_overdue(int days_after) const {
	int num_overdue = 0;
	for (const library_item *li : this->catalogue) {
		if (li->is_late(days_after))
			num_overdue++;
	}
	return num_overdue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include "library.h"

using namespace std;

int main() {
	library l;
	book b;
	journal j;
	b.loan();
	j.loan();
	l.add_library_item(&b);
	l.add_library_item(&j);
	cout << l.how_many_overdue(10) << endl;
	return 0;
}

Problem: 이와 같은 메인함수를 작성해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include "library.h"

using namespace std;

library* make_small_library() {
	library* l = new library;
	book b;
	journal j;
	b.loan();
	j.loan();
	l->add_library_item(&b);
	l->add_library_item(&j);
	return l;
}

int main() {
	library* l = make_small_library(); // 에러가 나는 이유: 함수의 스택이 파괴되면서 안에 있는 멤버 변수들까지 파괴됨 (stack-buffer-underflow)
	cout << l->how_many_overdue(10) << endl;
	delete l;
	return 0;
}

해결법: 1 catalogue에 포인터 넣지 말고 클래스 자체를 넣기 2 bj를 힙에 넣어서 (new, delete) 스택이 파괴되어도 사라지지 않도록 하기 3 shared ptr

LIBRARY CLASS with shared ptr

library.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef LIBRARY_H
#define LIBRARY_H

#include <vector>
#include <memory>

class library_item;

class library {
	std::vector<std::shared_ptr<library_item>> catalogue;
public:
	library() : catalogue(std::vector<std::shared_ptr<library_item>>()) {}
	void add_library_item(std::shared_ptr<library_item>);
	int how_many_overdue(int days_after) const;
};

class library_item {
	bool is_checked_out;
public:
	virtual int borrowing_period() const { return 7; }
	library_item() : is_checked_out(false) {}
	virtual void loan() { this->is_checked_out = true; }
	virtual void give_back() { this->is_checked_out = false; }
	virtual bool can_borrow() const { return !this->is_checked_out; }
	virtual bool is_late(int days_after) const {
		return days_after > this->borrowing_period();
	}
};

class book : public library_item {
public:
	book() : library_item() {}
	virtual int borrowing_period() const { return 14; }
};

class journal : public library_item {
public:
	journal() : library_item() {}
};

#endif

library.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "library.h"

using namespace std;

void library::add_library_item(shared_ptr<library_item> new_item) {
	this->catalogue.push_back(new_item);
}

int library::how_many_overdue(int days_after) const {
	int num_overdue = 0;
	for (const shared_ptr<library_item> li : this->catalogue) {
		if (li->is_late(days_after))
			num_overdue++;
	}
	return num_overdue;
}

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <memory>
#include "library.h"

using namespace std;

library* make_small_library() {
	library* l = new library;
	shared_ptr<book> b = shared_ptr<book>(new book);
	shared_ptr<journal> j = shared_ptr<journal>(new journal);
	b->loan();
	j->loan();
	l->add_library_item(b);
	l->add_library_item(j);
	return l;
}

int main() {
	library* l = make_small_library();
	cout << l->how_many_overdue(10) << endl;
	delete l;
	return 0;
}
This post is licensed under CC BY 4.0 by the author.
Trending Tags