'C++'에 해당되는 글 24건

  1. 2021.01.23 가상 함수에서 메서드 호출
  2. 2021.01.22 Virtual
  3. 2021.01.22 Swap
  4. 2021.01.21 범위(Scope)
  5. 2021.01.21 포인터 연산자 예제
  6. 2021.01.21 예제1
  7. 2021.01.12 static
  8. 2021.01.11 is a / has a
  9. 2021.01.11 C++ 문제 풀이
  10. 2020.12.17 소켓 프로그래밍 함수와 Winsock2
#include <iostream>
#include <string>

using namespace std;

// person 클래스
class Person {
    char m_name[32]; // 이름
    int m_num; // 주민번호
public:
    Person(const char *name, int num);
    const char* getName() const { return m_name; }
    int getNum() const { return m_num; }
    virtual void print() const; // 가상 함수
};

// Person 생성자
Person::Person(const char *name, int num) : m_num(num) {
    strcpy(m_name, name);
}

// Person 정보 출력
void Person::print() const {
    cout << " [사람 정보] " << endl;
    cout << " 이름 : " << m_name << endl;
    cout << " 주민번호 : " << m_num << endl;
    cout << " 객체크기 = " << sizeof(Person) << endl;
}

// Student 클래스
class Student : public Person {
    int m_sno; // 학번
    char m_dept[32]; // 소속 학과
public:
    Student(const char* name, int num, int sno, const char* dept);
    int getSno() const { return m_sno; }
    const char* getDept() const { return m_dept; }
    void print() const;
};


// Student 생성자
Student::Student(const char* name, int num, int sno, const char* dept) : Person(name, num), m_sno(sno) {
    strcpy(m_dept, dept);
}

// Student 정보 출력
void Student::print()const {
    cout << " [학생 정보] " << endl;
    cout << " 이름 : " << getName() <<endl;
    cout << " 주민번호 : " << getNum() << endl;
    cout << " 학번 : " << m_sno << endl;
    cout << " 소속 학과 : " << m_dept << endl;
    cout << " 객체 크기 : " << sizeof(Student) << endl;
}

// Employee 클래스
class Employee : public Person {
    int m_eno; // 사번
    float m_wage; // 임금
public:
    Employee(const char* name, int num, int eno, float wage);
    int getEno() const { return m_eno; }
    float getWage() const { return m_wage; }
    void print() const;
};

// Employee 생성자
Employee::Employee(const char* name, int num, int eno, float wage) : Person(name, num), m_eno(eno), m_wage(wage) {
    
}

// Employee 정보 출력
void Employee::print() const {
    cout << " [사원 정보] " << endl;
    cout << " 이름 : " << getName() << endl;
    cout << " 주민번호 : " << getNum() << endl;
    cout << " 사번 : " << m_eno << endl;
    cout << " 임금 : " << m_wage << endl;
    cout << " 객체 크기 : " << sizeof(Employee) << endl;
}

// Professor 클래스
class Professor : public Employee {
    int m_level; // 직급
    char m_dept[32]; // 소속 학과
public:
    Professor(const char* name, int num, int eno, float wage, int level, const char* dept);
    int getLevel() const { return m_level;}
    const char* getDept() const { return m_dept;}
    void print() const;
};

// Professor 생성자
Professor::Professor(const char* name, int num, int eno, float wage, int level, const char* dept) : Employee(name, num, eno, wage), m_level(level) {
    strcpy(m_dept, dept);
}

// Professor 정보 출력
void Professor::print() const {
    cout << " [교수 정보] " << endl;
    cout << " 이름 : " << getName() << endl;
    cout << " 주민 번호 : " << getNum() << endl;
    cout << " 사번 : " << getEno() << endl;
    cout << " 임금 : " << getWage() << endl;
    cout << " 직급 : " << m_level << endl;
    cout << " 소속 학과 : " << m_dept << endl;
    cout << " 객체 크기 = " << sizeof(Professor) << endl;
}

// 테스트
int main(int argc, const char * argv[]) {
    Person A("khon", 1234567);
    Student B("khon01", 1357912, 9512, "가나다라마");
    Employee C("khon02", 1535756, 6543, 1.0e6f);
    Professor D("khon03", 1485623, 8456, 2.0e6f, 2, "기니디리미");
    
    Person *P; // 부모 클래스 타입의 포인터
    
    P = &A; P->print(); cout << endl;
    P = &B; P->print(); cout << endl;
    P = &C; P->print(); cout << endl;
    P = &D; P->print(); cout << endl;
    return 0;
}

 

실행 결과

 [사람 정보] 

 이름 : khon

 주민번호 : 1234567

 객체크기 = 48

 

 [학생 정보] 

 이름 : khon01

 주민번호 : 1357912

 학번 : 9512

 소속 학과 : 가나다라마

 객체 크기 : 80

 

 [사원 정보] 

 이름 : khon02

 주민번호 : 1535756

 사번 : 6543

 임금 : 1e+06

 객체 크기 : 56

 

 [교수 정보] 

 이름 : khon03

 주민 번호 : 1485623

 사번 : 8456

 임금 : 2e+06

 직급 : 2

 소속 학과 : 기니디리미

 객체 크기 = 88

 

 

120행

- Person 클래스 타입의 포인터 P가 Person 타입의 객체를 가리키고, print 멤버 함수를 호출하고 있음

- 당연히 Person 클래스의 멤버 함수를 호출

 

121행

- P가 Student 타입의 객체를 가리키는 경우, P에 대해 print 멤버 함수를 호출하니까 정확히 p가 가리키는 객체의 타입인 Student 클래스의 멤버 함수를 호출하고 있음

 

122, 123행

- 120행과 마찬가지로 p가 가리키는 객체의 타입에 해당하는 멤버 함수를 호출하고 있음

- 가상 함수에 대해서는 포인터 타입의 메서드가 호출되는 것이 아니라 객체 타입의 메서드가 호출됨

'C++' 카테고리의 다른 글

Virtual  (0) 2021.01.22
Swap  (0) 2021.01.22
범위(Scope)  (0) 2021.01.21
포인터 연산자 예제  (0) 2021.01.21
예제1  (0) 2021.01.21
Posted by khon98
,

Virtual

C++ 2021. 1. 22. 18:10
#include <iostream>

using namespace std;

class Employee { // 부모 클래스
protected:
    long BaseSalary;
public:
    Employee();
    virtual void GetSalary();
};

class Manager : public Employee { // 파생 클래스
protected:
    long ManagerSalary;
public:
    Manager();
    void GetSalary();
};

class Salesman : public Employee { // 파생 클래스
protected:
    long SalesSalary;
public:
    Salesman();
    void GetSalary();
};

class Temporary : public Employee { // 파생 클래스
protected:
    long TempSalary;
public:
    Temporary();
    void GetSalary();
};

void Employee::GetSalary() {
    cout << " 사원 기본급 = " << BaseSalary << endl;
}

void Manager::GetSalary() {
    cout << " 사원 기본급 + 직급 수당 = " << (BaseSalary + ManagerSalary) << endl;
}

void Temporary::GetSalary() {
    cout << " 사원 기본급 + 계약 수당 = " << (BaseSalary + TempSalary) << endl;
}

void Salesman::GetSalary() {
    cout << " 사원 기본급 + 영업 수당 = " << (BaseSalary + SalesSalary) << endl;
}

Employee::Employee() { BaseSalary = 500000; }
Manager::Manager() { ManagerSalary = 300000; }
Salesman::Salesman() { SalesSalary = 200000; }
Temporary::Temporary() {TempSalary = 100000; }

int main(int argc, const char * argv[]) {
    Employee E, *ptrE;
    Manager M;
    Salesman S;
    Temporary T;
    ptrE = &E; ptrE->GetSalary();
    ptrE = &M; ptrE->GetSalary();
    ptrE = &S; ptrE->GetSalary();
    ptrE = &T; ptrE->GetSalary();
    
    return 0;
}

 

실행 결과

 사원 기본급 = 500000

 사원 기본급 + 직급 수당 = 800000

 사원 기본급 + 영업 수당 = 700000

 사원 기본급 + 계약 수당 = 600000

 

 

---------------------------------------------

#include <iostream>
#include <string>

using namespace std;

class Member { // 부모 클래스
    char *name;
public:
    Member(char *irum) { // 부모 클래스의 생성자
        name = new char[strlen(irum) + 1];
        strcpy(name, irum);
    }
    
    ~Member() { // 부모 클래스의 소멸자
        cout << " Member 소멸자 호출 " << endl;
        delete []name;
    }
    
    virtual void print() {
        cout << " 이름 : " << name << endl;
    }
};

class CallBonus : public Member { // 파생 클래스
private:
    char *id;
    int this_month;
    int special;
    int accumulation;
public:
    CallBonus(char *a, char *b, int c, int d, int e) :Member(a) { // 파생 클래스 생성자
        id = new char[strlen(b) + 1];
        strcpy(id, b);
        this_month = c;
        special = d;
        accumulation = e;
    }
    
    ~CallBonus() { // 파생 클래스 소멸자
        cout << " CallBonus 소멸자 호출 " << endl;
        delete []id;
    }
    
    void print() {
        Member::print();
        cout << " 주민등록번호 : " << id << endl;
        cout << " 당월 : " << this_month << endl;
        cout << " 특별 : " << special << endl;
        cout << " 누적 : " << accumulation << endl;
    }
};

int main(int argc, const char * argv[]) {
    Member *ptr;
    ptr = new CallBonus("khon", "111111-1234567", 200, 100, 1000);
    ptr->print();
    delete ptr;
    
    return 0;
}

 

실행 결과

 이름 : khon

 주민등록번호 : 111111-1234567

 당월 : 200

 특별 : 100

 누적 : 1000

 Member 소멸자 호출 

 

 

9행

- 부모 클래스 Member의 생성자 함수에 동적 메모리 할당 코드가 있기 때문에 소멸자에서 메모리 제거 코드가 만들어짐

 

24 ~ 42행

- 파생 클래스 CallBonus도 생성자에서 동적 메모리 할당 코드가 있고 파생 클래스의 소멸자에서는 할당된 영역을 제거하는 코드가 있음

 

55행

- 내용이 수행되면 최초로 부모 클래스의 생성자 함수가 호출되면서 데이터 멤버 name에 대한 메모리가 할당되고 다음에 파생 클래스의 생성자 함수가 호출되면서 데이터 멤버 id, this_month, special, accumulation에 대한 동적 메모리가 할당됨

 

57행

- 생성자가 호출되고 나서 delete ptr 코드에 의해서 소멸자가 호출, 먼저 파생 클래스의 소멸자가 호출되면서 할당된 메모리를 제거하고 다음에 부모 클래스의 소멸자가 호출되면서 할당된 메모리를 제거해야 함

- 결과를 보면 부모 클래스의 소멸자만 호출되는 것을 확인할 수 있음

- 이러한 문제는 가상 소멸자를 사용해서 해결할 수 있음

'C++' 카테고리의 다른 글

가상 함수에서 메서드 호출  (0) 2021.01.23
Swap  (0) 2021.01.22
범위(Scope)  (0) 2021.01.21
포인터 연산자 예제  (0) 2021.01.21
예제1  (0) 2021.01.21
Posted by khon98
,

Swap

C++ 2021. 1. 22. 13:15
#include <iostream>

using namespace std;

void swap(int*, int*);
void swap(char*, char*);
void swap(double*, double*);

int main(int argc, const char * argv[]) {
    int i = 123, j = 456;
    char a = 'A', b = 'B';
    double x = 123.45, y = 678.90;
    
    cout << " swap 이전 \n";
    cout << " i = " << i << ", j = " << j << endl;
    cout << " a = " << a << ", b = " << b << endl;
    cout << " x = " << x << ", y = " << y << '\n' << endl;
    
    swap(&i, &j);
    swap(&a, &b);
    swap(&x, &y);
    
    cout << " swap 이후 \n";
    cout << " i = " << i << ", j = " << j << endl;
    cout << " a = " << a << ", b = " << b << endl;
    cout << " x = " << x << ", y = " << y << endl;
    
    return 0;
}

void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

void swap(char *a, char *b) {
    char t = *a;
    *a = *b;
    *b = t;
}

void swap(double *a, double *b) {
    double t = *a;
    *a = *b;
    *b = t;
}

 

실행 결과

 swap 이전 

 i = 123, j = 456

 a = A, b = B

 x = 123.45, y = 678.9

 

 swap 이후 

 i = 456, j = 123

 a = B, b = A

 x = 678.9, y = 123.45

'C++' 카테고리의 다른 글

가상 함수에서 메서드 호출  (0) 2021.01.23
Virtual  (0) 2021.01.22
범위(Scope)  (0) 2021.01.21
포인터 연산자 예제  (0) 2021.01.21
예제1  (0) 2021.01.21
Posted by khon98
,

범위(Scope)

C++ 2021. 1. 21. 11:00
#include <iostream>

using namespace std;

int a = 1; // 파일 범위

int f(int a); // 함수 원형 범위

class C {
    int a; // 클래스 범위
public:
    C() { a = 10; }
    void g(); // 클래스 범위
};

void C::g() { // 클래스 멤버 함수
    cout << a << ' ' << ::a << ' ' << f(C::a) << endl;
}

int f(int n) { // 일반(전역)함수
    return n;
}

int main(int argc, const char * argv[]) {
    int b = 2; // 지역 범위(main 함수)
    cout << a << ' ' << b << endl;
    {
        int c = 3; // 지역 범위(안쪽 블록)
        cout << a << ' ' << b << ' ' << c << endl;
        goto L;
        cout << "여기는 절대로 호출되지 않음";
    }
    
    L: // 함수 범위
    C obj;
    obj.g();
    cout << f(5) << endl;
    return 0;
}

 

실행 결과

1 2 

1 2 3

10 1 10

5

 

 

5행

- a는 파일 범위를 가지는 전역 변수, 이 변수는 임의 블록에서 사용 가능

- 이 전역 변수의 이름과 동일한 것이 여러 곳에서 쓰이고 있지만 범위가 각각 다름

- 함수 f()도 파일 범위를 가짐

- 이런 일반 함수는 기본적으로 전역 함수임

- 전역 변수 a와 마찬가지로 프로그램 내 임의의 블록에서 사용할 수 있음

 

7행

- 함수 원형 범위를 설명해 주는 것으로 f()의 함수 원형의 형식 인자로 쓰인 변수 a는 이 원형에서만 유효함

- a나 클래스 범위 변수 a(10행)와는 관련이 없음

 

16행

- 클래스 C의 데이터 멤버 a와 멤버 함수 g()는 클래스 범위를 가짐

- 멤버 함수 g()를 클래스 바깥에서 정의할 때는 클래스 범위를 지정하는 연산자 ::를 사용

 

18행 

- 같은 이름을 같은 변수에 대한 해결이 필요한 예를 보이고 있음

- 전역 변수로서의 a는 임의의 블록에서 사용될 수 있지만 블록 내에 그 이름으로 선언된 변수가 있으면 그 변수가 우선순위를 가짐

- a는 클래스 블록의 a, 클래스 멤버를 지칭

- 전역 변수를 지칭하려면 단항 연산자로서의 전역 범위 연산자(::)를 변수 앞에 붙여야 함

- 클래스 멤버를 나타내는 확실한 방법은 역시 클래스 범위 연산자를 사용하는 것

 

28, 32행

- 지역 범위를 갖는 변수는 28행과 32행에 있음

- 변수 b는 main() 함수 블록에서 사용이 가능함(물론 안쪽 블록에서도 가능)

- 그러나 변수 c는 자신이 선언된 블록에서만 유효

- 함수 f()를 정의하는 21행에서 형식 인자 n이 지역 범위를 갖는 또 다른 변수

- 함수 f()를 c언어 방식으로 정의하면 n이 함수 블록에서만 유효하다는 것을 직관적으로 알 수 있음

int f(n)

int n:

{

 return n;

}

 

38행

- 함수 범위에 해당하는 변수가 포함되어 있음, goto문의 명칭 L은 main() 함수에서만 의미가 있음

'C++' 카테고리의 다른 글

Virtual  (0) 2021.01.22
Swap  (0) 2021.01.22
포인터 연산자 예제  (0) 2021.01.21
예제1  (0) 2021.01.21
static  (0) 2021.01.12
Posted by khon98
,

포인터 연산자 예제

C++ 2021. 1. 21. 10:25
#include <iostream>

using namespace std;

class C {
public:
    int m;
    void f(int i) { m += i; };
};

int C::*pm = &C::m;
typedef void (C::*ptr2memberFunc) (int);
ptr2memberFunc pf = &C::f;

int main(int argc, const char * argv[]) {
    C obj;
    obj.*pm = 100;
    (obj.*pf) (200);
    cout << obj.m << endl;
    
    C *pt = new C;
    pt->*pm = 300;
    (pt->*pf) (400);
    cout << pt->m << endl;
    return 0;
}

 

실행결과

300

700

 

 

7 ~ 8

- 7행은 클래스 C의 데이터 멤버이고 8행은 멤버 함수, 이들 멤버를 지정하는 간단한 방법은 멤버 선택 연산자의 도트 연산자(.)를 사용하는 것

 

11 ~ 13

- 11행은 클래스 C의 데이터 멤버 m을 포인터 변수 pm이 가리키는 것이고, 12, 13행은 클래스 C의 멤버 함수 f를 포인터 변수 pf가 가리키는 것, pf는 멤버 함수에 대한 포인터를 나타냄, 12행은 리턴 타입이 void이고 int 인자를 받는 클래스 C의 멤버 함수에 대해 포인터를 ptr2memberFunc라는 이름으로 선언한 것

'C++' 카테고리의 다른 글

Swap  (0) 2021.01.22
범위(Scope)  (0) 2021.01.21
예제1  (0) 2021.01.21
static  (0) 2021.01.12
is a / has a  (0) 2021.01.11
Posted by khon98
,

예제1

C++ 2021. 1. 21. 09:59
#include <iostream>

using namespace std;

const int ROW = 3;
const int COL = 3;

class Matrix {
    int m_row, m_col; // 행과 열
    double *m_data; // 행렬 데이터
public:
    Matrix(int r = ROW, int c = COL);
    
    Matrix(const Matrix &other);
    
    Matrix& operator = (const Matrix &other);
    
    ~Matrix() { delete [] m_data; };
    
    Matrix operator + (const Matrix &other) const;
    
    friend ostream& operator << (ostream& os, const Matrix& M);
        
    double& operator () (int i, int j) { return m_data[i * m_col + j]; }
    
    double operator () (int i, int j) const {return m_data[i * m_col + j]; }
};

// 생성자
Matrix::Matrix(int r, int c) {
    m_row = r;
    m_col = c;
    m_data = new double[r * c];
}

// 복사 생성자
Matrix::Matrix(const Matrix &other) {
    m_row = other.m_row;
    m_col = other.m_col;
    m_data = new double[m_row * m_col];
    for (int i = 0; i < m_row; i++)
    for (int j = 0; j < m_col; j++)
    m_data[i * m_col + j] = other.m_data[i * m_col + j];
}

// 대입 연산자
Matrix&
Matrix::operator = (const Matrix &other) {
    if ( this == &other ) return *this;
    delete [] m_data;
    m_row = other.m_row;
    m_col = other.m_col;
    m_data = new double[m_row * m_col];
    for (int i = 0; i < m_row; i++)
    for (int j = 0; j < m_col; j++)
    m_data[i * m_col + j] = other.m_data[i * m_col + j];
    return *this;
}

// 행렬의 덧셈
Matrix
Matrix::operator + (const Matrix& other) const {
    Matrix result;
    
    for (int i = 0; i < m_row; i++)
    for (int j = 0; j < m_col; j++)
    result(i, j) = m_data[i * m_col + j] + other.m_data[i * m_col + j];
    
    return result;
}

// 출력 연산자
ostream& operator << (ostream& os, const Matrix& M) {
    for (int i = 0; i < M.m_row; i++) {
        for (int j = 0; j < M.m_col; j++)
        os << M(i, j) << '\t';
        os << endl;
    }
    return os;
}

int main(int argc, const char * argv[]) {
    Matrix D, B, C;
    for (int i = 0; i < ROW; i++)
    for (int j = 0; j < COL; j++)
    B(i, j) = D(i, j) = i + j;
    C = D + B;
    cout << C;
    return 0;
}

 

실행 결과

0 2 4

2 4 6 

4 6 8 

 

 

8 ~ 27 - 클래스를 선언, 클래스를 통해 사용자 타입 Matrix를 만듦

9 ~ 10 - 행렬의 자료구조를 나타냄

12 ~ 26 - 행렬에 대한 연산을 나타냄, 클래스는 객체의 자료구조와 그 객체에 대한 연산을 함께 묶어 제공

30 ~ 80 - 클래스 선언 이후, 즉 클래스에서 제공하는 연산에 대한 정의

82 ~ 90 - main() 함수 부분이 서비스를 사용하는 클라이언트 코드이고, 그 이전 코드는 모두 서비스를 제공하기 위한 서버 코드

'C++' 카테고리의 다른 글

범위(Scope)  (0) 2021.01.21
포인터 연산자 예제  (0) 2021.01.21
static  (0) 2021.01.12
is a / has a  (0) 2021.01.11
C++ 문제 풀이  (0) 2021.01.11
Posted by khon98
,

static

C++ 2021. 1. 12. 16:06

출처 : 도서 - 그림으로 배우는 C++ Programming Basic

 

 

정적 멤버의 원리

- 클래스는 객체에 연결되지 않은 멤버를 가질 수도 있음 이를 '클래스 전체에 연결되었다'라고 부름

- 클래스에 연결된 멤버는 정적 멤버(Static Member)라고 부름

- 정적 멤버가 되는 데이터 멤버 및 멤버 함수를 선언할 때는 static이라고 하는 기억 클래스 지정자를 붙여야 함

 

#include <iostream>

using namespace std;

// Car 클래스 선언
class Car {
private:
    int num;
    double gas;
public:
    static int sum; // 정적 데이터 멤버
    Car();
    void setCar(int n, double g);
    void show();
    static void showSum(); // 정적 멤버 함수
};

// Car 클래스 멤버 함수의 정의
Car::Car() {
    num = 0;
    gas = 0.0;
    sum++;
    cout << "자동차가 만들어졌습니다. \n"; // 생성자가 호출될 때 정적 데이터 멤버 sum의 값을 1증가 시킴
}

void Car::setCar(int n, double g) {
    num = n;
    gas = g;
    cout << "차량 번호를 " << num << "으로, 연료량을 " << gas << "으로 바꾸었습니다. \n";
}

void Car::showSum() { // 정적 멤버 함수 정의
    cout << "자동차는 모두 " << sum << "대 있습니다. \n";
}

void Car::show() {
    cout << "차량 번호는 " << num << "입니다." << endl;
    cout << "연료량은 " << gas << "입니다" << endl;
}

int Car::sum = 0; // 정적 데이터 멤버 초기화

// Car 클래스의 이용
int main(int argc, const char * argv[]) {
    Car::showSum(); // 정적 데이터 함수 호출
    
    Car car1; // 객체 생성
    car1.setCar(7777, 95.7);
    
    Car::showSum(); // 정적 데이터 함수를 한번 더 호출
    
    Car car2;
    car2.setCar(9999, 72.4);
    
    Car::showSum();
    
    return 0;
}

자동차는 모두 0대 있습니다. // 정적 멤버 함수는 0대라고 출력

자동차가 만들어졌습니다. // 객체가 생성

차량 번호를 7777으로, 연료량을 95.7으로 바꾸었습니다. 

자동차는 모두 1대 있습니다. // 정적 멤버 함수는 1대라고 출력

자동차가 만들어졌습니다. 

차량 번호를 9999으로, 연료량을 72.4으로 바꾸었습니다. 

자동차는 모두 2대 있습니다. 

Program ended with exit code: 0

--------------------------------------

 

static int sum; // static을 붙여 정적 멤버로 만듦

 

sum은 클래스와 연결되어 있기 때문에 각 객체의 생성자 안에서 초기화시킬 수 없음

함수 바깥에서 Car::를 붙여 초기화시킴

자동차 객체가 하나 생성될 때마다 생성자 안에서는 sum++라는 문장이 실행, 그 결과 값이 1씩 증가

결과적으로 변수 sum은 Car 클래스를 통해 몇 대의 자동차가 만들어졌는지(객체의 개수가 몇 개인지)를 저장하는 필드가 된 것

 

정적 데이터 멤버란, 같은 클래스의 모든 객체들이 공통적으로 접근해야 하는 데이터를 저장하는 데이터 멤버

 

static void showSum(); // 정적 멤버 함수

 

멤버 함수에 static을 붙이면 객체를 생성하지 않더라도 호출할 수 있음

정적 멤버 함수는 객체를 생성하지 않은 상태에서도 호출할 수 있어야 하기 때문에 일반적인 함수와 호출 방법이 다름

 

정적 멤버 함수의 호출

클래스명 :: 함수명(인수 목록);

Car :: showSum(); // 클래스 이름을 붙여서 함수를 호출

 

정적 멤버 함수 안에서는 일반 멤버에 접근할 수 없음

정적 멤버 함수 또한 특정한 객체에 연결된 것이 아니기 때문

'C++' 카테고리의 다른 글

포인터 연산자 예제  (0) 2021.01.21
예제1  (0) 2021.01.21
is a / has a  (0) 2021.01.11
C++ 문제 풀이  (0) 2021.01.11
소켓 프로그래밍 함수와 Winsock2  (0) 2020.12.17
Posted by khon98
,

is a / has a

C++ 2021. 1. 11. 18:17

https://modoocode.com/210

 

씹어먹는 C++ - <6 - 2. 가상(virtual) 함수와 다형성>

 

modoocode.com

기반 클래스 = 부모 클래스

파생 클래스 = 자식 클래스

 

 

1. is a

- 모든 상속 관계는 is a라고 볼 수 있음, 이를 뒤 바꾸면 성립되지 않음

- 모든 클래스들의 관계는 is a 로만 표현할 수 없음

- 어떤 클래스들 사이에서는 is a 대신에 has a 관계가 성립되기도 함

 

class Manger(파생 클래스) : public Employee(기반 클래스)

 

- Manager 클래스는 Employee의 모든 기능을 포함한다

- Manager를 Employee라고 봐도 무방

- Manager is a Employee

- Employee는 Manager가 아님

- Manager는 Employee로 부를 수 있지만, Employee는 Manager로 부를 수 없음

 

2. has a

- 자동차는 엔진을 가진다 car has a engine, 자동차는 브레이크를 가진다 car has a brake

 

class car {

 pirvate:

  Engine e;

  Brake b;

}

 

- Employeelist는 Employee와 has a 관계임, employee를 포함하고 있음을 알 수 있음

 

class EmployeeList {

 int alloc_employee; // 할당한 총 직원수

 int current_employee; // 현재 직원 수

 Employee **employee_list; // 직원 데이터

}

 

 

EmployeeList

#include <iostream>

class EmployeeList {
    int alloc_employee; // 할당한 총 직원수
    
    int current_employee; // 현재 직원 수
    int current_manager; // 현재 매니저 수
    
    Employee **employee_list; // 직원 데이터
    Manager **manager_list; // 매니저 데이터
};

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    return 0;
}

위 코드에서 가장 문제 되는 것은 각 클래스 별로 따로 데이터를 보관해야 한다는 것

Employee는 Employee * 가 가리켜야 하고, Manager들은 Manager * 가 가리켜야 함

업 캐스팅은 자유롭게 수행될 수 있음

Employee * 가 Manager 객체를 가리켜도 별 문제가 없다는 것

 

void print_employee_info() {
    int total_pay = 0;
    for (int i = 0; i < current_employee; i++) {
        employee_list[i]->print_info();
        total_pay += employee_list[i]->calculate_pay();
}

employee_list[i]->printf_info()를 하게 되면 무조건 Employee 클래스의 print_info 함수가 호출

employee_list[i]는 Employee 객체를 가리키는 포인터이기 때문에 자신이 가리키는 객체가 Employee 객체라고 생각함

Manager 객체와 Employee 객체 모두 Employee* 가 가리키도록 하였으므로,

만일 employee_list[i] 가 가리키는 것이 Manager 객체 일 때, Manager의 print_info함수가 아니라 

Employee의 print_info함수가 호출되서 다른 결과를 냄

마찬가지로 calculate_pay 함수도 Manager의 calculate_pay 가 호출되어야 하는데 

Employee의 calculate_pay가 호출되어서 틀린 결과가 나옴

 

#include <iostream>
#include <string>

using namespace std;

class Employee {
protected:
    string name;
    int age;
    
    string position; // 직책 (이름)
    int rank; // 순위 (값이 클 수록 높은 순위)
public:
    Employee(string name, int age, string position, int rank)
    : name(name), age(age), position(position), rank(rank) {}
    
    // 복사 생성자
    Employee(const Employee& employee) {
        name = employee.name;
        age = employee.age;
        position = employee.position;
        rank = employee.rank;
    }
    
    // 디폴트 생성자
    Employee() {}
    
    void print_info() {
        cout << name << " (" << position << " , " << age << ") ==> " << calculate_pay() << "만원" << endl;
    }
    int calculate_pay() { return 200 + rank * 50; }
};

class Manager : public Employee {
    int year_of_service;
public:
    Manager(string name, int age, string position, int rank, int year_of_service)
    : year_of_service(year_of_service), Employee(name, age, position, rank) {}
    
    // 복사 생성자
    Manager(const Manager& manager)
    : Employee(manager.name, manager.age, manager.position, manager.rank) {
        year_of_service = manager.year_of_service;
    }
    
    // 디폴트 생성자
    Manager() : Employee() {}
    
    int calculate_pay() { return 200 + rank * 50 + year_of_service; }
    void print_info(){
        cout << name << " (" << position << " , " << age << " , " << year_of_service << "년차) ==> " << calculate_pay() << "만원" << endl;
    }
};

class EmployeeList {
    int alloc_employee; // 할당한 총 직원 수
    int current_employee; // 현재 직원 수
    Employee** employee_list; // 직원 데이터
public:
    EmployeeList(int alloc_employee) : alloc_employee(alloc_employee) {
        employee_list = new Employee*[alloc_employee];
        
        current_employee = 0;
    }
    void add_employee(Employee* employee) {
        // current_employee 보다 alloc_employee가 더 많아지는 경우
        // 반드시 재할당을 해야 하지만 여기서는 최대한 단순하게 생각해서
        // alloc_employee는 언제나 current_employee 보다 크다고 생각함
        // 즉 할당된 크기는 현재 총 직원수 보다 많음
        employee_list[current_employee] = employee;
        current_employee++;
    }
    int current_employee_num() { return current_employee; }
    
    void print_employee_info() {
        int total_pay = 0;
        for (int i = 0; i < current_employee; i++) {
            employee_list[i]->print_info();
            total_pay += employee_list[i]->calculate_pay();
        }
        cout << "총 비용 : " << total_pay << "만원 " << endl;
    }
    ~EmployeeList() {
        for (int i = 0; i < current_employee; i++) {
            delete employee_list[i];
        }
        delete[] employee_list;
    }
};


int main(int argc, const char * argv[]) {
    EmployeeList emp_list(10);
    emp_list.add_employee(new Employee("khon01", 10, "평사원", 1));
    emp_list.add_employee(new Employee("khon02", 20, "평사원", 1));
    emp_list.add_employee(new Manager("khon03", 30, "부장", 7, 12));
    emp_list.add_employee(new Manager("khon04", 40, "과장", 4, 15));
    emp_list.add_employee(new Manager("khon05", 28, "차장", 5, 13));
    emp_list.add_employee(new Employee("khon06", 52, "대리", 2));
    emp_list.add_employee(new Employee("khon07", 24, "인턴", -2));
    emp_list.print_employee_info();

    return 0;
}

전부다 Employee의 print_info와 calculate_pay 함수가 호출되서 원래 결과와 달라짐

'C++' 카테고리의 다른 글

예제1  (0) 2021.01.21
static  (0) 2021.01.12
C++ 문제 풀이  (0) 2021.01.11
소켓 프로그래밍 함수와 Winsock2  (0) 2020.12.17
소켓 프로그래밍의 개요  (0) 2020.12.17
Posted by khon98
,

C++ 문제 풀이

C++ 2021. 1. 11. 16:06

[부모 클래스]

  조건2. class Cleaning cpp 구현해야 되는 내용

 

     - static int m_total_personner; .cpp 파일에서 초기화 합니다.

     - int m_personnel;  .cpp 생성자에서 초기화합니다..

 

     해당 함수는 부모 클래스(class Cleaning)에 구현합니다.

     void setCleaningPersonnel(int person);

     int getCleaningPersonner();

 

 [분야별 클래스 구현]

    1 바닥청소 / 창문청소 / 화장실 청소 분야별 클래스를 부모클래스를 상속받아 구현합니다.

    2 각 분야별 청소 객체를 main 함수에서 동적 생성합니다.

    3 각 분야 객체별로 setCleaningPersonnel 함수를 사용해서 바닥청소 5 / 창문청소 10 / 화장실청소 8명으로 지정하고

아래 [결과물] [결과물]과 같이 출력되야 됩니다.

      

       - 청소 준비 : (생성자)에서생성자) 출력

       - 청소 시작 : run() 함수에서 출력

       - 총 청소 인원 : main 함수에서 출력

       - 청소 종료 : (소멸자)에서소멸자) 출력

 

[결과물]

 

 [청소 준비]

 [Child] 바닥 청소 클래스 준비!

 [Child] 창문 청소 클래스 준비!

 [Child] 화장실 청소 클래스 준비!

 

 [청소 시작]

 ==>[실행] 바닥 청소 5명 시작!

 ==>[실행] 창문 청소 10명 시작!

 ==>[실행] 화장실 청소 8명 시작!

 

 [총 청소 인원]

 ==>[실행] 23명이 청소를 하고 있습니다.

 

 [청소 종료]

 [Child] 바닥 청소 클래스 종료!

 [Child] 창문 청소 클래스 종료!

 [Child] 화장실 청소 클래스 종료!

 

--------------------------------------------------

main.cpp

 

#include <iostream>
#include "Cleaning.hpp"
#include "FloorCleaning.hpp"
#include "WindowCleaning.hpp"
#include "BathroomCleaning.hpp"

using namespace std;

int main(int argc, const char * argv[]) {
    FloorCleaning* fc = new FloorCleaning;
    WindowCleaning* wc = new WindowCleaning;
    BathroomCleaning* bc = new BathroomCleaning;
    
    fc->setCleaningPersonnel(5);
    wc->setCleaningPersonnel(10);
    bc->setCleaningPersonnel(8);
    
    fc->run();
    wc->run();
    bc->run();
    
    printf(" 총 청소 인원 : 총 %d명이 청소를 하고 있습니다\r\n", Cleaning::getTotalCleaningPersonner());
    
    delete fc;
    delete wc;
    delete bc;
    
    return 0;
}

--------------------------------------------------

 

 

--------------------------------------------------

Cleaning.cpp

 

#include <iostream>
#include "Cleaning.hpp"

// 구현부

int Cleaning::m_total_personner = 0; // 전체 청소 인원수 초기화

Cleaning :: Cleaning() { // 생성자
    m_personnel = 0; // 분야별 청소 인원수 초기화
}

Cleaning :: ~Cleaning() { // 소멸자
}

//분야별 청소 인원 세팅
void Cleaning :: setCleaningPersonnel(int person){
    m_personnel = person;
    m_total_personner += person;
}

//분야별 청소 인원 수 가져오는 함수
int Cleaning:: getCleaningPersonner() {
    return m_personnel;
}

// 전체 청소 인원수
int Cleaning::getTotalCleaningPersonner() {
    return m_total_personner;
}

--------------------------------------------------

 

 

--------------------------------------------------

FloorCleaning.cpp

 

#include <iostream>
#include "FloorCleaning.hpp"

using namespace std;

FloorCleaning :: FloorCleaning() {
    cout << " 청소 준비 : 바닥 청소 클래스 준비" << endl;
}

FloorCleaning :: ~FloorCleaning() {
    cout << " 청소 종료 : 바닥 청소 클래스 청소 종료" << endl;
}

void FloorCleaning :: run() {
    printf(" 청소 시작 : 바닥 청소 %d명 시작\r\n", getCleaningPersonner());
}

--------------------------------------------------

 

 

--------------------------------------------------

WindowCleaning.cpp

 

#include <iostream>
#include "WindowCleaning.hpp"

using namespace std;

WindowCleaning::WindowCleaning(){
    cout << " 청소 준비 : 창문 청소 클래스 청소 준비" << endl;
}

WindowCleaning::~WindowCleaning(){
    cout << " 청소 종료 : 창문 청소 클래스 청소 종료" << endl;
}

void WindowCleaning::run(){
    printf(" 청소 시작 : 창문 청소 %d명 시작\r\n", getCleaningPersonner());
}

--------------------------------------------------

 

 

--------------------------------------------------

BathroomCleaning.cpp

 

#include <iostream>
#include "BathroomCleaning.hpp"

using namespace std;

BathroomCleaning::BathroomCleaning(){
    cout << " 청소 준비 : 화장실 청소 클래스 청소 준비" << endl;
}

BathroomCleaning::~BathroomCleaning(){
    cout << " 청소 종료 : 화장실 청소 클래스 청소 종료" << endl;
}

void BathroomCleaning::run(){
    printf(" 청소 시작 : 화장실 청소 %d명 청소 시작\r\n", getCleaningPersonner());
}

--------------------------------------------------

 

 

--------------------------------------------------

Cleaning.hpp

 

//
//  CCleaning.hpp
//  Test201226
//
//  Created by DongOh Lim on 2020/12/26.
//

#ifndef CCleaning_hpp
#define CCleaning_hpp

#include <stdio.h>

// 선언부
class Cleaning {
private:
    static int m_total_personner; // 전체 청소 인원수
    int m_personnel;              // 분야별 청소 인원수
public:
    Cleaning();             // 생성자
    virtual ~Cleaning();    // 소멸자
    
    //분야별 청소 인원 세팅
    void setCleaningPersonnel(int person);
    
    //분야별 청소 인원 수 가져오는 함수
    int getCleaningPersonner();
    
    //전체 청소인원
    static int getTotalCleaningPersonner();
    
    // 청소 시작 함수
    virtual void run() = 0;
};

#endif

--------------------------------------------------

 

 

--------------------------------------------------

FloorCleaning.hpp

 

#ifndef FloorCleaning_hpp
#define FloorCleaning_hpp

#include <iostream>
#include <stdio.h>
#include "Cleaning.hpp"

using namespace std;

class FloorCleaning : public Cleaning {
public:
    FloorCleaning();
    
    ~FloorCleaning();
    
    virtual void run();
};
#endif /* FloorCleaning_hpp */

--------------------------------------------------

 

 

--------------------------------------------------

WindowCleaning.hpp

 

#ifndef WindowCleaning_hpp
#define WindowCleaning_hpp

#include <stdio.h>
#include "Cleaning.hpp"

class WindowCleaning : public Cleaning {
public:
    WindowCleaning();
    
    ~WindowCleaning();
    
    virtual void run();
};

#endif /* WindowCleaning_hpp */

--------------------------------------------------

 

 

--------------------------------------------------

BathroomCleaning.hpp

 

#ifndef BathroomCleaning_hpp
#define BathroomCleaning_hpp

#include <stdio.h>
#include "Cleaning.hpp"

class BathroomCleaning : public Cleaning {
public:
    BathroomCleaning();
    
    ~BathroomCleaning();
    
    virtual void run();
};

#endif /* BathroomCleaning_hpp */

--------------------------------------------------

'C++' 카테고리의 다른 글

static  (0) 2021.01.12
is a / has a  (0) 2021.01.11
소켓 프로그래밍 함수와 Winsock2  (0) 2020.12.17
소켓 프로그래밍의 개요  (0) 2020.12.17
예외 처리  (0) 2020.12.16
Posted by khon98
,

socket(네트워크 주소 체계, 소켓 타입, 프로토콜)

- 소켓을 생성하는 함수

- 이 함수는 '네트워크 주소 체계', '소켓 타입', '프로토콜'로 초기화할 수 있음

- 소켓 생성에 실패하는 경우 -1을 반환함

- 네트워크 주소 체계 : IPv4(AF_INET), IPv6(AF_INET6)

- 소켓 타입 : TCP(SOCK_STREAM), UDP(SOCK_DGRAM)

- 프로토콜 : TCP(IPPROPTO_TCP), UDP(IPPOTO_UDP)

 

bind(소켓 변수, 서버 주소 구조체, 서버 주소 구조체의 크기)

- 서버 측의 소켓에 IP와 포트 번호를 할당하여 네트워크 인터페이스와 묶일 수 있도록 함

- IPv4 소켓 주소 구조체(SOCKADDR_IN) : 소켓 주소체계(sin_family), 포트(sin_port), IPv4 주소(sin_addr)

- 실제로 소켓 주소 구조체를 이용할 때는 IPv4 소켓 주소 구조체를 일반 소켓 구조체로 변환하여 사용해야 함

 

listen(소켓 변수, 백 로그 큐의 크기)

- 클라이언트로부터 연결 요청을 기다림

- 백 로그란 동시에 연결을 시도하는 최대 클라이언트 수를 의미

 

connect(소캣 변수, 서버 주소 구조체, 서버 주소 구조체 크기)

- 클라이언트 측에서 서버에 연결을 요청함

- 소켓 생성에 실패하는 경우 -1을 반환

- IPv4 소켓 주소 구조체 : 소켓 주소체계(sin_family), 포트 번호(sin_port), IPv4 주소(sin_addr)

- 실제로 소켓 주소 구조체를 이용할 때는 IPv4 소켓 주소 구조체를 일반 소켓 구조체로 변환하여 사용해야 함

 

accept(소켓 변수, 클라이언트 주소 구조체 변수, 클라이언트 주소 구조체 크기)

- 서버 측에서 클라이언트의 연결을 수락

- accept() 함수 내부에서 클라이언트 주소를 설정한 뒤에 통신에 사용할 클라이언트의 소켓을 반환함

- 오류가 발생하는 경우 -1을 반환

- 실제로 소켓 주소 구조체를 이용할 때는 IPv4 소켓 주소 구조체를 일반 소켓 구조체로 변환하여 사용해야 함

 

send(소켓 변수, 문자열 버퍼, 문자열 버퍼 크기, 플래그)

- 상대방에게 데이터를 보냄

- 특정한 소켓으로 문자열 버퍼에 담긴 내용을 전송

- 플래그는 특별한 경우가 아니라면 0을 설정함

- 데이터 전송에 실패하는 경우 -1을 반환

 

recv(소켓 변수, 문자열 버퍼, 문자열 버퍼 크기, 플래그)

- 데이터를 수신하여 특정 문자열 버퍼를 담음

- 플래그는 특별한 경우가 아니라면 0을 성정

- 데이터 수신에 실패하는 경우 -1을 반환

 

closesocket(소켓 변수)

- 열린 소켓을 닫음

 

Winsock2

- Windows Socket API의 준말로 네트워크 프로그래밍을 위한 라이브러리

- Winsock을 사용하기 위해서는 ws2_32.dll 파일을 사용 설정해야 하며 WSAStartup() 함수 등을 통해 환경 설정을 진행해야 함

- Winsock2는 윈도우를 위한 소켓 프로그래밍 라이브러리이므로 리눅스 프로그램에서는 사용할 필요가 없음

 

WSAStartup(윈속 버전, WSA데이터 변수)

- 사용할 Winsock의 버전을 설정

- 관련 설정 정보를 받기 위해 WSADATA 변수를 함께 넣어줌

 

WSACleanup()

- Winsock을 더 이상 사용하지 않음을 설정

'C++' 카테고리의 다른 글

is a / has a  (0) 2021.01.11
C++ 문제 풀이  (0) 2021.01.11
소켓 프로그래밍의 개요  (0) 2020.12.17
예외 처리  (0) 2020.12.16
STL 연관 컨테이너  (0) 2020.12.16
Posted by khon98
,